1. Lighthouse

Level 2 · How big is the table?

The request

From Priya Shah, Head of Data

“Finance says there are about 30,000 order lines in the system. Can you confirm the exact number of rows in order_items?”

Your goal

Set result to the number of rows in order_items, as an int.

  • Use the order_items DataFramenot done yet
  • Store a number in resultnot done yet

Your code

Python

Loading the editor…

    ResultPreview of order_items · press Run to see yours
    Preview of order_items
    order_item_idorder_idproduct_idquantityunit_price
    11001121931.99
    21001154311.99
    31002154411.99
    410021941149.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.

    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
    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
    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
    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
    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

    Rows and columns

    Before any analysis, check the size of what you’ve got:

    order_items.shape        # (rows, columns)
    order_items.shape[0]     # number of rows
    order_items.shape[1]     # number of columns
    len(order_items)         # number of rows, the most common way to write it

    shape is an attribute, not a method, so it has no brackets. It’s a tuple, which you index like a list.

    Row counts are your first sanity check. If the business says “about 30,000 order lines” and you see 3,000 or 300,000, stop and find out why before going further. Maybe the file was truncated, maybe you loaded the wrong table, maybe the business number is out of date. Any of those is worth knowing.

    Column names

    order_items.columns
    # Index(['order_item_id', 'order_id', 'product_id', 'quantity',
    #        'unit_price', 'discount_pct'], dtype='object')
    
    list(order_items.columns)   # as a plain list

    Column names are case-sensitive and must match exactly, so it’s worth looking at them before typing them in code.

    Types with dtypes and info

    Every column has a dtype (data type). The ones you’ll see most:

    dtype holds
    int64 whole numbers
    float64 decimals, and whole numbers in a column with missing values
    bool True / False
    object text (and anything mixed)
    datetime64[ns] dates and times, once converted
    order_items.dtypes

    info() puts everything in one view: number of rows, each column’s non-null count and dtype, and memory use.

    customers.info()
    RangeIndex: 2018 entries, 0 to 2017
    Data columns (total 9 columns):
     #   Column           Non-Null Count  Dtype
    ---  ------           --------------  -----
     0   customer_id      2018 non-null   int64
     ...
     4   city             2004 non-null   object
     ...
     8   referral_source  1352 non-null   object

    Two discoveries in one glance: some customers have no city, and about a third have no referral source. info() prints its report rather than returning a value, so use it to look, not to store.

    Types tell you about the data

    Types often reveal problems before you see them in rows. In web_sessions, customer_id is float64 rather than int64. Why would an ID be a decimal? Because some sessions are anonymous, and a classic NumPy integer column can’t hold missing values, so pandas stores the column as floats with NaN. Similarly, order_date shows datetime64[ns] only because the tables here were loaded with pd.read_csv(..., parse_dates=[...]). CSV files don’t carry types, so a plain read_csv would leave dates as object text. Spotting these early saves you from confusing errors later.

    Other quick checks

    order_items["order_id"].nunique()   # distinct orders that have lines
    order_items.isna().sum()            # missing values per column

    Common mistakes

    • Writing order_items.shape() with brackets: TypeError: 'tuple' object is not callable.
    • Storing order_items.info() in a variable. It prints and returns None.
    • Using order_items.size for the row count. size is rows times columns.