1. Lighthouse

Level 5 · Which product numbers move together?

The request

From Priya Shah, Head of Data

“Merchandising keeps asking one pair at a time: price and units, price and returns, margin and revenue. Give me the whole correlation matrix for our product metrics and the three strongest pairs, so we stop guessing which ones are worth a deeper look.”

Your goal

Using per_product from the starter (columns unit_price, units_sold, revenue, return_rate, margin, in that order), set result to a DataFrame with the 3 pairs of different columns that have the largest absolute correlation, strongest first: columns var_1, var_2 (the pair, var_1 being the one that comes first in per_product) and r (the correlation with its sign, rounded to 3), index reset.

  • Use the products DataFramenot done yet
  • Use the orders DataFramenot done yet
  • Show exactly var_1 var_2 rnot done yet
Correlations between product metrics (120 products)
Correlations between product metrics (120 products)unit_priceunits_soldrevenuereturn_ratemarginunit_priceunit_price × unit_price: 11.00unit_price × units_sold: -0.43-0.43unit_price × revenue: 0.380.38unit_price × return_rate: 0.160.16unit_price × margin: -0.23-0.23units_soldunits_sold × unit_price: -0.43-0.43units_sold × units_sold: 11.00units_sold × revenue: 0.140.14units_sold × return_rate: -0.05-0.05units_sold × margin: 0.10.10revenuerevenue × unit_price: 0.380.38revenue × units_sold: 0.140.14revenue × revenue: 11.00revenue × return_rate: 0.110.11revenue × margin: -0.17-0.17return_ratereturn_rate × unit_price: 0.160.16return_rate × units_sold: -0.05-0.05return_rate × revenue: 0.110.11return_rate × return_rate: 11.00return_rate × margin: 0.040.04marginmargin × unit_price: -0.23-0.23margin × units_sold: 0.10.10margin × revenue: -0.17-0.17margin × return_rate: 0.040.04margin × margin: 11.00
Correlations between product metrics (120 products)unit_priceunits_soldrevenuereturn_ratemarginunit_priceunit_price × unit_price: 11.00unit_price × units_sold: -0.43-0.43unit_price × revenue: 0.380.38unit_price × return_rate: 0.160.16unit_price × margin: -0.23-0.23units_soldunits_sold × unit_price: -0.43-0.43units_sold × units_sold: 11.00units_sold × revenue: 0.140.14units_sold × return_rate: -0.05-0.05units_sold × margin: 0.10.10revenuerevenue × unit_price: 0.380.38revenue × units_sold: 0.140.14revenue × revenue: 11.00revenue × return_rate: 0.110.11revenue × margin: -0.17-0.17return_ratereturn_rate × unit_price: 0.160.16return_rate × units_sold: -0.05-0.05return_rate × revenue: 0.110.11return_rate × return_rate: 11.00return_rate × margin: 0.040.04marginmargin × unit_price: -0.23-0.23margin × units_sold: 0.10.10margin × revenue: -0.17-0.17margin × return_rate: 0.040.04margin × margin: 11.00

Orange is a positive correlation, blue a negative one; the stronger the colour, the closer r is to +1 or -1. The diagonal is always 1: every column matches itself.

Show the numbers
unit_priceunits_soldrevenuereturn_ratemargin
unit_price1.00-0.430.380.16-0.23
units_sold-0.431.000.14-0.050.10
revenue0.380.141.000.11-0.17
return_rate0.16-0.050.111.000.04
margin-0.230.10-0.170.041.00

Your code

Python

Loading the editor…

    ResultPreview of products · press Run to see yours
    Preview of products
    product_idnamecategorysubcategoryunit_price
    101Vale Velvet LoveseatFurnitureSofas1659.00
    102Alder Oak Coffee TableFurnitureTables919.00
    103Orchard Rattan Dining ChairFurnitureChairs789.00
    104Upland Oak BookcaseFurnitureStorage429.00

    Mote checks your result

    Press Run. Each row that matches the goal becomes a firefly in your lantern.

    DataFrames

    Loaded for you as pandas DataFrames, plus pd and np.

    products120 rows · 8 columns
    • product_idinteger
    • namevarchar
    • categoryvarchar
    • subcategoryvarchar
    • unit_pricedecimal
    • unit_costdecimal
    • launched_ondate
    • is_activeboolean
    First 5 rows of products
    product_idnamecategorysubcategoryunit_priceunit_costlaunched_onis_active
    101Vale Velvet LoveseatFurnitureSofas1659.00NaN2023-09-11true
    102Alder Oak Coffee TableFurnitureTables919.00503.502024-05-16true
    103Orchard Rattan Dining ChairFurnitureChairs789.00429.872023-05-27true
    104Upland Oak BookcaseFurnitureStorage429.00214.702022-12-20true
    105Avery Leather Bed FrameFurnitureBeds449.00232.702021-08-31true
    orders12,000 rows · 7 columns
    • order_idinteger
    • customer_idinteger
    • order_datetimestamp
    • statusvarchar
    • channelvarchar
    • shipping_feedecimal
    • coupon_codevarchar
    First 5 rows of orders
    order_idcustomer_idorder_datestatuschannelshipping_feecoupon_code
    10011252023-01-01 20:51:19completedweb0.00NaN
    10021562023-01-02 07:58:46completedweb0.00NaN
    1003222023-01-02 10:25:27completedmarketplace4.99WELCOME10
    1004482023-01-02 11:21:51completedmarketplace4.99WELCOME10
    1005822023-01-02 11:43:36completedweb0.00WELCOME10
    order_items30,338 rows · 6 columns
    • order_item_idinteger
    • order_idinteger
    • product_idinteger
    • quantityinteger
    • unit_pricedecimal
    • discount_pctdecimal
    First 5 rows of order_items
    order_item_idorder_idproduct_idquantityunit_pricediscount_pct
    11001121931.990.00
    21001154311.990.00
    31002154411.990.00
    410021941149.000.00
    51002193219.990.00
    returns1,673 rows · 5 columns
    • return_idinteger
    • order_item_idinteger
    • returned_ondate
    • reasonvarchar
    • refund_amountdecimal
    First 5 rows of returns
    return_idorder_item_idreturned_onreasonrefund_amount
    1142023-01-10damaged83.69
    2422023-01-10wrong_item19.99
    31052023-01-14wrong_item10.99
    4242023-01-16changed_mind26.99
    51262023-01-16late20.99
    customers2,018 rows · 9 columns
    • customer_idinteger
    • first_namevarchar
    • last_namevarchar
    • emailvarchar
    • cityvarchar
    • statevarchar
    • signup_datedate
    • segmentvarchar
    • referral_sourcevarchar
    First 5 rows of customers
    customer_idfirst_namelast_nameemailcitystatesignup_datesegmentreferral_source
    1OwenHudsonowen.hudson@icloud.comSan FranciscoCA2022-06-02consumersearch
    2DouglasMendozadmendoza69@gmail.comAtlantaGA2022-06-02consumerNaN
    3HenryBrookshbrooks@lakesidecafe.comLos AngelesCA2022-06-04businessNaN
    4BrianGrahambgraham@bluecedarhomes.comSeattleWA2022-06-06businesspinterest
    5KyleJimenezkjimenez27@yahoo.comIndianapolisIN2022-06-07consumerNaN
    employees60 rows · 8 columns
    • employee_idinteger
    • first_namevarchar
    • last_namevarchar
    • departmentvarchar
    • titlevarchar
    • manager_idinteger
    • hire_datedate
    • salaryinteger
    First 5 rows of employees
    employee_idfirst_namelast_namedepartmenttitlemanager_idhire_datesalary
    1CatherineHaleExecutiveChief Executive OfficerNaN2016-03-01285000
    2RobertKimExecutiveChief Operating Officer12017-01-09235000
    3MeganCollinsSalesHead of Sales12018-04-16172000
    4ChloeGutierrezSalesAccount Executive32020-01-2172000
    5FrankBellSalesAccount Executive32023-05-2173000
    web_sessions40,000 rows · 7 columns
    • session_idinteger
    • customer_idinteger
    • started_attimestamp
    • devicevarchar
    • sourcevarchar
    • pages_viewedinteger
    • convertedboolean
    First 5 rows of web_sessions
    session_idcustomer_idstarted_atdevicesourcepages_viewedconverted
    1NaN2023-01-01 23:02:24mobilepaid1false
    2182023-01-01 15:07:49desktoppaid1false
    3NaN2023-01-01 16:55:46desktopdirect7false
    4NaN2023-01-01 12:43:28mobileorganic3false
    5NaN2023-01-01 13:06:21mobilesocial2false
    marketing_spend3,276 rows · 3 columns
    • spend_datedate
    • channelvarchar
    • amountdecimal
    First 5 rows of marketing_spend
    spend_datechannelamount
    2023-01-01paid492.99
    2023-01-01email37.38
    2023-01-01social200.53
    2023-01-02paid709.13
    2023-01-02email64.13

    The lesson

    One call, every pair

    Level 1 measured one pair. When a table has several numeric columns, DataFrame.corr() measures all of them at once and returns a square correlation matrix: one row and one column per variable, r in every cell.

    per_product.corr().round(2)

    Three things are always true of it. The diagonal is 1 (each column against itself). The matrix is symmetric: the cell for price and units equals the cell for units and price. And pandas uses the rows where both columns have values, so the 9 products without a cost still count in every pair that does not involve margin.

    Reading it as a heatmap

    Twenty-five numbers are hard to scan, so the matrix is usually drawn as a heatmap: one coloured cell per pair, the number printed inside. Two rules make a correlation heatmap honest:

    • A fixed scale from -1 to +1. If the colours stretch to the strongest value in this table, a weak 0.4 is painted as dark as a near-perfect 0.95 would be in another table.
    • A diverging palette: one colour for positive, another for negative, pale near zero. Here orange is positive and blue is negative.

    On the chart, the darkest off-diagonal cell is price against units sold, in blue.

    Strong, moderate, weak

    A common rule of thumb: |r| above 0.7 is strong, 0.3 to 0.7 moderate, below 0.3 weak. On Harbor & Pine’s products only two pairs are even moderate: price and units sold (-0.425) and price and revenue (0.375). Everything else is below 0.25, and return rate is barely related to anything.

    Rank pairs by the absolute value, then report the sign: “price and units sold have the strongest relationship, a moderate negative one”.

    The grain changes the answer

    You might expect units sold and revenue to move together strongly. Across products they hardly do (r = 0.14), because a product that sells 900 cheap units can earn less than one that sells 50 sofas. Count the same two numbers per month and r is 0.95: busy months are busy in units and dollars. Per order it is 0.60. A correlation describes the rows you computed it on, so always say what one row is.

    Common mistakes

    • Sorting by r instead of |r|. Strong negative pairs end up at the bottom.
    • Counting pairs twice and keeping the diagonal. Use only the cells above the diagonal.
    • Letting the colour scale float. Fix it at -1 to 1.
    • Writing “causes”. A matrix shows which columns are associated; say “is associated with” or “tends to go with”, and check the scatter plot before anything else.

    Pick what may run on this site. You can change this any time from "Cookie settings" at the bottom of every page.