The request

From Jessica Turner, Merchandising Manager
Your goal
Set result to a dict with two keys, both rounded to 3 decimals: "pearson", the correlation between per_product["unit_price"] and per_product["units_sold"], and "rank", the correlation between their ranks (.rank() of each column, then .corr()).
- Use the
productsDataFramenot done yet - Use the
ordersDataFramenot done yet - Store a dict in
resultnot done yet
The dashed line is the best straight line through the dots. The dots bend: steep at low prices, nearly flat above $500.
Show the numbers
| List price | Units sold, 2023–2025 |
|---|---|
| $31.99 | 571 |
| $11.99 | 1,568 |
| $159 | 787 |
| $19.99 | 2,320 |
| $25.99 | 812 |
| $53.99 | 1,349 |
| $92.99 | 507 |
| $349 | 309 |
| $20.99 | 2,017 |
| $159 | 559 |
| $66.99 | 96 |
| $70.99 | 423 |
| $1,599 | 163 |
| $28.99 | 2,300 |
| $239 | 293 |
| $17.99 | 1,704 |
| $149 | 214 |
| $179 | 384 |
| $189 | 606 |
| $27.99 | 842 |
| $25.99 | 601 |
| $76.99 | 433 |
| $259 | 370 |
| $104.99 | 1,325 |
| $189 | 568 |
| $13.99 | 1,035 |
| $289 | 205 |
| $169 | 592 |
| $53.99 | 772 |
| $159 | 190 |
| $45.99 | 687 |
| $179 | 268 |
| $379 | 1,046 |
| $38.99 | 664 |
| $54.99 | 648 |
| $179 | 354 |
| $109 | 545 |
| $43.99 | 1,122 |
| $179 | 766 |
| $189 | 629 |
| $109 | 324 |
| $369 | 101 |
| $72.99 | 467 |
| $29.99 | 1,318 |
| $93.99 | 747 |
| $409 | 113 |
| $18.99 | 402 |
| $10.99 | 1,527 |
| $329 | 139 |
| $84.99 | 360 |
| $179 | 195 |
| $449 | 152 |
| $30.99 | 546 |
| $199 | 305 |
| $52.99 | 1,645 |
| $50.99 | 716 |
| $259 | 143 |
| $78.99 | 180 |
| $219 | 317 |
| $129 | 196 |
| $86.99 | 83 |
| $289 | 514 |
| $23.99 | 517 |
| $249 | 331 |
| $629 | 98 |
| $439 | 79 |
| $79.99 | 206 |
| $74.99 | 509 |
| $779 | 37 |
| $429 | 39 |
| $1,099 | 208 |
| $51.99 | 238 |
| $1,379 | 33 |
| $779 | 88 |
| $1,609 | 105 |
| $689 | 56 |
| $219 | 64 |
| $969 | 45 |
| $669 | 53 |
| $169 | 115 |
| $349 | 465 |
| $13.99 | 743 |
| $789 | 37 |
| $16.99 | 853 |
| $219 | 114 |
| $72.99 | 169 |
| $1,659 | 44 |
| $60.99 | 792 |
| $999 | 208 |
| $1,209 | 25 |
| $109 | 105 |
| $169 | 492 |
| $379 | 34 |
| $15.99 | 454 |
| $179 | 100 |
| $239 | 54 |
| $19.99 | 1,061 |
| $919 | 46 |
| $20.99 | 744 |
| $229 | 377 |
| $30.99 | 226 |
| $17.99 | 295 |
| $189 | 167 |
| $519 | 77 |
| $159 | 71 |
| $44.99 | 790 |
| $51.99 | 211 |
| $70.99 | 356 |
| $139 | 138 |
| $139 | 447 |
| $289 | 23 |
| $12.99 | 407 |
| $109 | 135 |
| $279 | 29 |
| $279 | 8 |
| $18.99 | 195 |
| $1,289 | 6 |
| $17.99 | 305 |
| $103.99 | 35 |
| $869 | 13 |
Your code
Loading the editor…
Reference solution
| product_id | name | category | subcategory | unit_price |
|---|---|---|---|---|
| 101 | Vale Velvet Loveseat | Furniture | Sofas | 1659.00 |
| 102 | Alder Oak Coffee Table | Furniture | Tables | 919.00 |
| 103 | Orchard Rattan Dining Chair | Furniture | Chairs | 789.00 |
| 104 | Upland Oak Bookcase | Furniture | Storage | 429.00 |
Mote checks your result
Press Run. Each row that matches the goal becomes a firefly in your lantern.
What Jessica gets, and why
DataFrames
Loaded for you as pandas DataFrames, plus pd and np.
products120 rows · 8 columns
product_idintegernamevarcharcategoryvarcharsubcategoryvarcharunit_pricedecimalunit_costdecimallaunched_ondateis_activeboolean
| product_id | name | category | subcategory | unit_price | unit_cost | launched_on | is_active |
|---|---|---|---|---|---|---|---|
| 101 | Vale Velvet Loveseat | Furniture | Sofas | 1659.00 | NaN | 2023-09-11 | true |
| 102 | Alder Oak Coffee Table | Furniture | Tables | 919.00 | 503.50 | 2024-05-16 | true |
| 103 | Orchard Rattan Dining Chair | Furniture | Chairs | 789.00 | 429.87 | 2023-05-27 | true |
| 104 | Upland Oak Bookcase | Furniture | Storage | 429.00 | 214.70 | 2022-12-20 | true |
| 105 | Avery Leather Bed Frame | Furniture | Beds | 449.00 | 232.70 | 2021-08-31 | true |
orders12,000 rows · 7 columns
order_idintegercustomer_idintegerorder_datetimestampstatusvarcharchannelvarcharshipping_feedecimalcoupon_codevarchar
| order_id | customer_id | order_date | status | channel | shipping_fee | coupon_code |
|---|---|---|---|---|---|---|
| 1001 | 125 | 2023-01-01 20:51:19 | completed | web | 0.00 | NaN |
| 1002 | 156 | 2023-01-02 07:58:46 | completed | web | 0.00 | NaN |
| 1003 | 22 | 2023-01-02 10:25:27 | completed | marketplace | 4.99 | WELCOME10 |
| 1004 | 48 | 2023-01-02 11:21:51 | completed | marketplace | 4.99 | WELCOME10 |
| 1005 | 82 | 2023-01-02 11:43:36 | completed | web | 0.00 | WELCOME10 |
order_items30,338 rows · 6 columns
order_item_idintegerorder_idintegerproduct_idintegerquantityintegerunit_pricedecimaldiscount_pctdecimal
| order_item_id | order_id | product_id | quantity | unit_price | discount_pct |
|---|---|---|---|---|---|
| 1 | 1001 | 121 | 9 | 31.99 | 0.00 |
| 2 | 1001 | 154 | 3 | 11.99 | 0.00 |
| 3 | 1002 | 154 | 4 | 11.99 | 0.00 |
| 4 | 1002 | 194 | 1 | 149.00 | 0.00 |
| 5 | 1002 | 193 | 2 | 19.99 | 0.00 |
customers2,018 rows · 9 columns
customer_idintegerfirst_namevarcharlast_namevarcharemailvarcharcityvarcharstatevarcharsignup_datedatesegmentvarcharreferral_sourcevarchar
| customer_id | first_name | last_name | city | state | signup_date | segment | referral_source | |
|---|---|---|---|---|---|---|---|---|
| 1 | Owen | Hudson | owen.hudson@icloud.com | San Francisco | CA | 2022-06-02 | consumer | search |
| 2 | Douglas | Mendoza | dmendoza69@gmail.com | Atlanta | GA | 2022-06-02 | consumer | NaN |
| 3 | Henry | Brooks | hbrooks@lakesidecafe.com | Los Angeles | CA | 2022-06-04 | business | NaN |
| 4 | Brian | Graham | bgraham@bluecedarhomes.com | Seattle | WA | 2022-06-06 | business | |
| 5 | Kyle | Jimenez | kjimenez27@yahoo.com | Indianapolis | IN | 2022-06-07 | consumer | NaN |
returns1,673 rows · 5 columns
return_idintegerorder_item_idintegerreturned_ondatereasonvarcharrefund_amountdecimal
| return_id | order_item_id | returned_on | reason | refund_amount |
|---|---|---|---|---|
| 1 | 14 | 2023-01-10 | damaged | 83.69 |
| 2 | 42 | 2023-01-10 | wrong_item | 19.99 |
| 3 | 105 | 2023-01-14 | wrong_item | 10.99 |
| 4 | 24 | 2023-01-16 | changed_mind | 26.99 |
| 5 | 126 | 2023-01-16 | late | 20.99 |
employees60 rows · 8 columns
employee_idintegerfirst_namevarcharlast_namevarchardepartmentvarchartitlevarcharmanager_idintegerhire_datedatesalaryinteger
| employee_id | first_name | last_name | department | title | manager_id | hire_date | salary |
|---|---|---|---|---|---|---|---|
| 1 | Catherine | Hale | Executive | Chief Executive Officer | NaN | 2016-03-01 | 285000 |
| 2 | Robert | Kim | Executive | Chief Operating Officer | 1 | 2017-01-09 | 235000 |
| 3 | Megan | Collins | Sales | Head of Sales | 1 | 2018-04-16 | 172000 |
| 4 | Chloe | Gutierrez | Sales | Account Executive | 3 | 2020-01-21 | 72000 |
| 5 | Frank | Bell | Sales | Account Executive | 3 | 2023-05-21 | 73000 |
web_sessions40,000 rows · 7 columns
session_idintegercustomer_idintegerstarted_attimestampdevicevarcharsourcevarcharpages_viewedintegerconvertedboolean
| session_id | customer_id | started_at | device | source | pages_viewed | converted |
|---|---|---|---|---|---|---|
| 1 | NaN | 2023-01-01 23:02:24 | mobile | paid | 1 | false |
| 2 | 18 | 2023-01-01 15:07:49 | desktop | paid | 1 | false |
| 3 | NaN | 2023-01-01 16:55:46 | desktop | direct | 7 | false |
| 4 | NaN | 2023-01-01 12:43:28 | mobile | organic | 3 | false |
| 5 | NaN | 2023-01-01 13:06:21 | mobile | social | 2 | false |
marketing_spend3,276 rows · 3 columns
spend_datedatechannelvarcharamountdecimal
| spend_date | channel | amount |
|---|---|---|
| 2023-01-01 | paid | 492.99 |
| 2023-01-01 | 37.38 | |
| 2023-01-01 | social | 200.53 |
| 2023-01-02 | paid | 709.13 |
| 2023-01-02 | 64.13 |
The lesson
What a correlation measures
The correlation coefficient r is a number from -1 to 1 that says how closely two columns move along a straight line:
- close to 1: when one is high, the other is high, almost on a rising line;
- close to -1: when one is high, the other is low, almost on a falling line;
- close to 0: no straight-line pattern.
In pandas it is one call on two Series of the same length:
per_product["unit_price"].corr(per_product["units_sold"]) # -0.425
Across Harbor & Pine’s 120 products, r is -0.425: pricier products sell fewer units, but the points are far from a tidy line. A common rule of thumb calls 0.1 weak, 0.3 moderate and 0.5 strong, but the number alone never tells you the shape. Look at the chart.
When Pearson undersells a curve
Pearson’s r (the default .corr()) rewards a straight line. The dots in the chart bend: units fall
steeply from $11 bowl sets and vases to $200 lamps, then barely change from $800 dining chairs
to the $1,659 loveseat. The dashed best-fit line misses both ends, so r looks only moderate.
A rank correlation (Spearman’s) asks a looser question: as price goes up, do units go down, whatever the shape? Replace each value with its rank (1 = cheapest) and correlate the ranks:
per_product["unit_price"].rank().corr(per_product["units_sold"].rank()) # -0.694
-0.694 is a strong negative relationship. With SciPy installed, .corr(method="spearman") gives the
same number; ranking first works everywhere, including this browser.
What r does not tell you
- Not the slope. r = -0.7 does not mean “each extra dollar costs 0.7 units”. The size of the effect is a regression question (level 3).
- Not the cause. The cheap end is kitchenware, decor and textiles, which far more customers shop for; the expensive end is furniture and outdoor sets. Price is tangled up with what the product is, so this chart cannot say what a price cut would do to units.
- Not robust to outliers. One product with huge sales can move r a lot. Ranks are much less sensitive.
Common mistakes
- Reporting r without the scatter plot. Very different shapes can share the same r.
- Calling a moderate r “no relationship”. Here r = -0.43 hides a strong, curved pattern.
- Mixing grains. Correlating price with units per order line instead of per product counts popular products hundreds of times. Decide what one row is (here: one product), build both columns in one DataFrame at that grain, then correlate.
Lantern lit!
Practised: correlationpearsonrank correlationscatter plot
- Solved
- No hints
- First run
