Pandas & NumPy Academy · Oppitunti

Menetelmien ketjutus pipe()-menetelmällä

Kirjoittakaa selkeitä datan muunnosputkia ketjuttamalla omia funktioita pipe()-menetelmällä Pandasin omien menetelmien rinnalle.

Oppitunti 4/413 vaihetta

Menetelmien ketjutus pipe()-menetelmällä on ilmainen Pandas & NumPy Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Pandas & NumPy Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Pandas & NumPy Academy-kurssilla on yhteensä 4 oppituntia.

Väliaikaisten muuttujien ongelma

Ilman pipe()-menetelmää tietojen puhdistusputkeen kertyy usein monia väliaikaisia muuttujia: df1 = clean(df), df2 = transform(df1), df3 = enrich(df2). Nämä muuttujat sotkevat nimiavaruutta, vaikeuttavat virheenkorjausta ja houkuttelevat kehittäjiä käyttämään niitä virheellisesti uudelleen. Tällöin koodia on vaikea lukea ylhäältä alas muunnosten sarjana.

import pandas as pd

df = pd.read_csv('orders.csv')

# Without pipe — intermediate variables everywhere
df1 = df.dropna(subset=['revenue'])
df2 = df1[df1['quantity'] > 0]
df3 = df2.assign(revenue_per_unit=df2['revenue'] / df2['quantity'])
print(df3.shape)

pipe()-menetelmän esittely

DataFrame.pipe(func) kutsuu func(df)-funktiota ja palauttaa tuloksen. Näin mukautettuja funktioita voidaan ketjuttaa samalla tavalla kuin Pandasin omia menetelmiä, kuten .dropna().query(). Keskeinen hyöty on, että jokainen muunnosvaihe on ilmaistu selkeästi ja luettavasti vasemmalta oikealle — tai sulkeilla muotoiltuna ylhäältä alas — ja järjestys vastaa putken loogista etenemistä.

def drop_nulls(df):
    return df.dropna(subset=['revenue'])

def filter_positive_qty(df):
    return df[df['quantity'] > 0]

def add_revenue_per_unit(df):
    return df.assign(revenue_per_unit=df['revenue'] / df['quantity'])

# With pipe — clean chain
df_clean = (df
    .pipe(drop_nulls)
    .pipe(filter_positive_qty)
    .pipe(add_revenue_per_unit)
)
print(df_clean.shape)

Argumenttien välittäminen pipe()-menetelmälle

Välittäkää lisäargumentit putkeen liitetylle funktiolle käyttämällä funktion nimen jälkeen nimettyjä argumentteja: df.pipe(func, arg1=val1). Funktion allekirjoituksen on hyväksyttävä df ensimmäisenä parametrina. Parametrisoidut funktiot tekevät putkesta muokattavan: voitte vaihtaa raja-arvoja, sarakkeiden nimiä tai toimintaa muuttamatta funktion runkoa, ainoastaan pipe-kutsun argumentteja muuttamalla.

def filter_by_region(df, regions):
    return df[df['region'].isin(regions)]

def cap_revenue(df, upper):
    df = df.copy()
    df['revenue'] = df['revenue'].clip(upper=upper)
    return df

df_result = (df
    .pipe(filter_by_region, regions=['North', 'East'])
    .pipe(cap_revenue, upper=1000)
)
print(df_result.shape)

pipe()-menetelmän yhdistäminen omiin menetelmiin

pipe()-funktion teho perustuu siihen, että se integroituu saumattomasti Pandasin natiivien metodien kanssa samassa ketjussa. Voitte yhdistää .dropna()-, .query()-, .rename()- ja .pipe(custom_func)-kutsuja missä tahansa järjestyksessä. Näin ketju on sekä tiivis (kun käytettävissä on sisäänrakennettu metodi) että joustava (kun sisäänrakennetut metodit eivät riitä).

df_result = (
    df
    .dropna(subset=['revenue', 'order_date'])
    .query('quantity > 0')
    .rename(columns={'unit_price': 'price'})
    .pipe(add_revenue_per_unit)
    .reset_index(drop=True)
)
print(df_result.head())

pipe()-ketjun virheenkorjaus

Pitkän ketjun virheenkorjaus voi olla hankalaa, koska ketjun keskelle ei voi lisätä tulostuslausetta välitilojen tarkastelemiseksi. Yksi ratkaisu on kirjoittaa debuggausta varten välitysfunktiona toimiva funktio, joka tulostaa muoto- ja saraketiedot ja palauttaa DataFramen muuttumattomana. Lisää se mihin tahansa ketjun kohtaan, jotta voit tarkastella tilaa kyseisessä vaiheessa katkaisematta ketjua.

def debug(df, label=''):
    print(f'[{label}] shape: {df.shape}')
    print(f'[{label}] columns: {df.columns.tolist()}')
    return df

df_result = (
    df
    .pipe(drop_nulls)
    .pipe(debug, label='after drop_nulls')
    .pipe(filter_positive_qty)
    .pipe(debug, label='after filter')
)
print('Done')

Täyden puhdistusputken rakentaminen

Yhdistä kaikki puhdistusvaiheet yhdeksi pipeline-funktioksi käyttämällä pipe()-funktiota. Kun ketju kääritään funktioon nimeltä clean_pipeline(df), pipelinea voidaan testata yhtenä kokonaisuutena. Kutsu funktiota käsittelemättömällä DataFramella ja saat tulokseksi puhtaan DataFramen. Tämä toimintamalli noudattaa tuotantotason data engineeringissä käytettävää ETL (Extract, Transform, Load) -mallia.

def clean_pipeline(df):
    return (
        df
        .dropna(subset=['order_id', 'revenue'])
        .drop_duplicates(subset=['order_id'])
        .query('quantity > 0 and revenue >= 0')
        .pipe(add_revenue_per_unit)
        .reset_index(drop=True)
    )

df_clean = clean_pipeline(df)
print('Clean rows:', len(df_clean))

pipe() ja apply(): keskeiset erot

pipe(func) välittää koko DataFramen funktiolle func ja odottaa saavansa takaisin DataFramen (tai muun muunnetun olion). apply(func, axis=1) käsittelee yhden rivin kerrallaan. Käyttäkää pipe()-funktiota koko DataFrameen kohdistuviin muunnoksiin, joissa muoto säilyy samana (tai muuttuu tarkoituksella), ja apply()-funktiota rivi- tai saraketasolla tehtäviin laskutoimituksiin. Ne täydentävät toisiaan eivätkä kilpaile keskenään.

# pipe: receives the whole DataFrame
def scale_revenue(df, factor=1.0):
    df = df.copy()
    df['revenue'] = df['revenue'] * factor
    return df

# apply: receives one row at a time
df['revenue_x2'] = df.apply(lambda row: row['revenue'] * 2, axis=1)

df_scaled = df.pipe(scale_revenue, factor=1.1)
print('pipe scales all rows at once; apply does row-by-row')

Uudelleenkäytettävät pipeline-komponentit

Kirjoittakaa jokainen pipelinen vaihe puhtaana funktiona — älkää käyttäkö globaalia tilaa, vastaanottakaa DataFrame ja palauttakaa DataFrame. Puhtaat funktiot on helppo testata yksikkötesteillä: kutsukaa funktiota pienellä testidatalla ja tarkistakaa tuloksen muoto ja sarakearvot. Testattujen ja uudelleenkäytettävien pipeline-funktioiden kirjasto nopeuttaa huomattavasti sellaisten uusien aineistojen analysointia, joilla on samankaltaisia puhdistusvaatimuksia.

def normalise_strings(df, cols):
    df = df.copy()
    for col in cols:
        df[col] = df[col].str.strip().str.lower()
    return df

def parse_dates(df, cols):
    df = df.copy()
    for col in cols:
        df[col] = pd.to_datetime(df[col])
    return df

df_result = (
    df
    .pipe(normalise_strings, cols=['region', 'category'])
    .pipe(parse_dates, cols=['order_date'])
)
print(df_result.dtypes)

Pipelinen vaiheiden kirjaaminen lokiin pipe()-funktiolla

Lisätkää jokaiseen pipeline-funktioon rakenteinen lokitus, jotta voitte tarkastaa jokaisen tuotannossa tehdyn muunnoksen. Sisällyttäkää syötteen rivimäärä, tuloksen rivimäärä ja olennaiset tilastotiedot (esimerkiksi suodatuksessa poistettujen rivien määrä). Näin saatte täydellisen jäljityksen jokaisesta pipelinen suorituksesta ilman ulkoista työnkulkujen orkestroijaa perusmuotoista auditointia varten.

import logging
logging.basicConfig(level=logging.INFO)

def logged_dropna(df, subset):
    before = len(df)
    df = df.dropna(subset=subset)
    after = len(df)
    logging.info(f'dropna: {before - after} rows removed, {after} remaining')
    return df

df_clean = df.pipe(logged_dropna, subset=['revenue'])
print('Logged pipeline complete.')

Ehdolliset vaiheet pipelinessä

Joskus puhdistusvaihe pitäisi suorittaa vain lipun arvon tai datan sisällön perusteella. Voitte lisätä pipe-ketjuun ehdollisia vaiheita sijoittamalla siihen identiteetti- tai muunnosfunktion: se tarkistaa ehdon ja joko suorittaa muunnoksen tai palauttaa DataFramen muuttumattomana. Näin ketjun rakenne säilyy ja valinnaiset vaiheet ovat mahdollisia.

def maybe_cap_revenue(df, cap=None):
    if cap is None:
        return df
    df = df.copy()
    df['revenue'] = df['revenue'].clip(upper=cap)
    return df

CAPPING_ENABLED = True
CAP_VALUE = 1000 if CAPPING_ENABLED else None

df_result = df.pipe(maybe_cap_revenue, cap=CAP_VALUE)
print('Conditional step applied:', CAPPING_ENABLED)

Pipelinen tuloksen vieminen

pipe()-ketjun viimeinen vaihe on usein tietojen vienti. Voitte ketjuttaa mukautetun vientifunktion käyttämällä pipe()-funktiota tai kutsua Pandasin natiivia vientimetodia suoraan ketjun jälkeen. Kun käytätte pipe(save_to_parquet)-vaihetta, vienti dokumentoidaan osaksi ketjua ja se suoritetaan varmasti viimeiselle puhdistetulle DataFramelle eikä välivaiheen versiolle.

def save_parquet(df, path):
    df.to_parquet(path, index=False)
    print(f'Saved {len(df)} rows to {path}')
    return df  # return df so the chain can continue if needed

df_final = (
    df
    .pipe(clean_pipeline)
    .pipe(save_parquet, path='orders_final.parquet')
)
print('Pipeline complete.')

Pikatarkistus

Testatkaa ymmärrystänne tämän oppitunnin data-analyysin käsitteistä.

Oppitunnin kertaus

Tällä oppitunnilla opitte: ketjuttamaan mukautettuja funktioita natiivien Pandas-metodien kanssa pipe()-funktiolla, rakentamaan uudelleenkäytettäviä, parametroitavia ja testattavia pipeline-vaiheita puhtaina funktioina sekä lisäämään debuggauslokituksen ja ehdollisia vaiheita pipe-ketjun sisään. Seuraavaksi tutustumme muunnosvaiheiden jäsentämiseen funktioiksi tuotantotason ETL-pipelinea varten.

Aloita maksutta

Opi Python tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
30
Oppitunnit
120

Usein kysytyt kysymykset

Onko oppitunti ”Menetelmien ketjutus pipe()-menetelmällä” ilmainen?

Kyllä – oppitunnin ”Menetelmien ketjutus pipe()-menetelmällä” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Pandas & NumPy Academy-kurssin, päivitä CoddyKit PROhon. Pandas & NumPy Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Menetelmien ketjutus pipe()-menetelmällä”?

Kirjoittakaa selkeitä datan muunnosputkia ketjuttamalla omia funktioita pipe()-menetelmällä Pandasin omien menetelmien rinnalle. Harjoittelet Pandas & NumPy Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Pandas & NumPy Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Pandas & NumPy Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.

Kuinka kauan ”Menetelmien ketjutus pipe()-menetelmällä”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Pandas & NumPy Academy-oppitunnilla?

Kyllä. Jokainen Pandas & NumPy Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. apply() sarakkeille ja riveille
  2. apply() GroupBy-toiminnon kanssa
  3. map() ja applymap() alkiokohtaisiin toimintoihin
  4. Menetelmien ketjutus pipe()-menetelmällä
← Takaisin: Pandas & NumPy Academy