Pandas & NumPy Academy · Oppitunti

apply() sarakkeille ja riveille

Käyttäkää DataFrame.apply()-menetelmää axis=0- ja axis=1-akseleilla suorittaaksenne mukautetun funktion jokaiselle sarakkeelle tai riville.

Oppitunti 1/413 vaihetta

apply() sarakkeille ja riveille on ilmainen Pandas & NumPy Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/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.

Milloin apply()-funktiota käytetään

DataFrame.apply() suorittaa mukautetun Python-funktion jokaiselle sarakkeelle (axis=0) tai riville (axis=1). Se on viimeinen vaihtoehto — hitaampi kuin sisäänrakennetut vektoroidut operaatiot — mutta välttämätön, kun laskentaa ei voi ilmaista NumPyn aritmetiikalla, boolean-indeksoinnilla tai sisäänrakennetuilla aggregointifunktioilla. Käyttäkää sitä, kun tarvitsette monimutkaista ehtologiikkaa, mukautettua merkkijonojen jäsentämistä tai monivaiheisia laskutoimituksia, jotka käsittelevät kerrallaan yhtä riviä tai saraketta.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'price': [10.5, 25.0, 8.3, 100.0],
    'quantity': [3, 1, 5, 2],
    'tax_rate': [0.05, 0.10, 0.05, 0.15]
})
print(df)

apply() sarakkeilla (axis=0)

Kun käytössä on axis=0 (oletusarvo), apply() välittää jokaisen sarakkeen Series-objektina funktiolle. Funktio saa yhden sarakkeen kerrallaan, ja sen tulisi palauttaa skalaariluku (aggregointia varten) tai Series (muunnosta varten). Tämä sopii mukautetun normalisointi- tai puhdistusvaiheen soveltamiseen yhdenmukaisesti kaikkiin numeerisiin sarakkeisiin yhdellä kutsulla.

# Custom range normalisation (0 to 1) for each column
def min_max_scale(col):
    return (col - col.min()) / (col.max() - col.min())

df_scaled = df[['price', 'quantity']].apply(min_max_scale, axis=0)
print(df_scaled)

apply() riveillä (axis=1)

Kun käytössä on axis=1, apply() välittää jokaisen rivin Series-objektina funktiolle. Rivin indeksi on sarakkeen nimi, joten arvoja voi käsitellä nimen perusteella. Tämä sopii rivitason laskutoimituksiin, jotka riippuvat useista sarakkeista, kuten verojen jälkeisen kokonaisliikevaihdon laskemiseen, kun jokaisella rivillä on oma veroprosenttinsa.

def revenue_after_tax(row):
    subtotal = row['price'] * row['quantity']
    return subtotal * (1 + row['tax_rate'])

df['revenue_after_tax'] = df.apply(revenue_after_tax, axis=1)
print(df)

Useiden arvojen palauttaminen apply()-funktiolla

apply(axis=1)-funktiolle välitetty funktio voi palauttaa nimetyt alkiot sisältävän pd.Series-objektin, jonka Pandas laajentaa useiksi uusiksi sarakkeiksi. Tämä on selkeämpää kuin apply()-funktion kutsuminen kahdesti kahden uuden sarakkeen luomiseksi. Vaihtoehtoisesti funktio voi palauttaa dict-objektin, jonka Pandas myös laajentaa sarakkeiksi.

def compute_totals(row):
    subtotal = row['price'] * row['quantity']
    tax = subtotal * row['tax_rate']
    return pd.Series({'subtotal': subtotal, 'tax': tax, 'total': subtotal + tax})

result = df.apply(compute_totals, axis=1)
print(result)

apply() mukautettuun sarakeaggregointiin

Käyttäkää apply(func, axis=0)-kutsua mukautetun tunnusluvun laskemiseen jokaiselle sarakkeelle ja yhteenveto-Series-objektin palauttamiseen. Voitte esimerkiksi laskea variaatiokertoimen (keskihajonta jaettuna keskiarvolla) kaikille numeerisille sarakkeille yhdellä kutsulla. Tuloksena on sarakenimen mukaan indeksoitu Series, joka sopii nopeaan sarakekohtaiseen diagnostiikkaan.

def coeff_of_variation(col):
    return col.std() / col.mean() if col.mean() != 0 else np.nan

cv = df[['price', 'quantity']].apply(coeff_of_variation, axis=0)
print('Coefficient of variation per column:')
print(cv)

apply()-funktion vertaaminen vektoroituihin vaihtoehtoihin

Tarkistakaa aina ennen apply()-funktion käyttöä, onko saatavilla vektoroitu vaihtoehto. Veron jälkeisen liikevaihdon laskennassa df['price'] * df['quantity'] * (1 + df['tax_rate']) tekee saman kuin apply(axis=1) -versio, mutta suorittuu 10–100 kertaa nopeammin, koska se käyttää NumPyn C-tason silmukoita. Käyttäkää apply()-funktiota vain tapauksissa, joissa vektoroitu logiikka olisi vaikeasti luettavaa.

import time

start = time.time()
df['vectorised'] = df['price'] * df['quantity'] * (1 + df['tax_rate'])
print('Vectorised:', time.time() - start, 's')

start = time.time()
df['apply_result'] = df.apply(revenue_after_tax, axis=1)
print('apply():', time.time() - start, 's')

apply() lambda-funktion kanssa

Lyhyissä yhden rivin muunnoksissa voitte välittää lambda-funktion suoraan apply()-funktiolle nimetyn funktion määrittämisen sijaan. Lambdat ovat ytimekkäitä yksinkertaisissa operaatioissa, mutta niitä tulisi välttää monimutkaisessa logiikassa, jossa nimetty, kommentein varustettu funktio on helpompi ymmärtää ja testata. Käyttäkää lambdoja säästeliäästi — niitä ei voi helposti yksikkötestata tai profiloida nimen perusteella.

# Clip revenue between 0 and 200, then round to nearest 10
df['revenue_clean'] = df['revenue_after_tax'].apply(lambda x: round(min(max(x, 0), 200) / 10) * 10)
print(df[['revenue_after_tax', 'revenue_clean']])

Lisäargumenttien välittäminen apply()-funktiolle

Välittäkää funktiolle lisäargumentteja käyttämällä args-monikkoa tai avainsana-argumentteja kutsussa apply(func, args=(val,), axis=1). Näin vältätte globaalien muuttujien käyttöä funktion sisällä ja teette funktiosta uudelleenkäytettävän eri parametriarvoilla. Python 3.8 -versiosta alkaen voitte käyttää myös functools.partial-funktiota osittain sovelletun funktion luomiseen.

def discount_price(row, discount_pct, threshold):
    if row['quantity'] >= threshold:
        return row['price'] * (1 - discount_pct)
    return row['price']

df['discounted_price'] = df.apply(
    discount_price, axis=1,
    args=(0.1, 3)  # 10% discount for quantity >= 3
)
print(df[['price', 'quantity', 'discounted_price']])

apply() tyyppimuunnoksiin

Kun sarake sisältää sekoitettuja tyyppejä — esimerkiksi kokonaislukuja, liukulukuja ja merkkijonoja — astype() aiheuttaa virheen. Käyttäkää apply(pd.to_numeric, errors='coerce') -kutsua muunnoksen yrittämiseen rivi kerrallaan; se palauttaa NaN-arvon arvoille, joita ei voi muuntaa. Tämä on turvallinen tapa käsitellä sarakkeita, joiden pitäisi olla numeerisia mutta joissa on satunnaisia tietojen syöttövirheistä johtuvia ei-numeerisia arvoja.

messy = pd.Series(['10', '20.5', 'N/A', '100', '--'])
clean = messy.apply(pd.to_numeric, errors='coerce')
print(clean)

Suorituskyky: apply() ja np.vectorize

Kun skalaareja käsittelevää funktiota on sovellettava alkio kerrallaan, np.vectorize(func)(array) on yleensä nopeampi kuin Series.apply(func), koska NumPyn vectorize käyttää C:n kautta tapahtuvaa kutsujen välitystä Pythonin funktiokutsujen aiheuttaman yleiskustannuksen sijaan. np.vectorize on kuitenkin edelleen hitaampi kuin aito broadcasting — siitä on hyötyä vain, kun mikään broadcasting-lauseke ei pysty ilmaisemaan logiikkaa.

def classify_size(price):
    if price < 15:
        return 'small'
    elif price < 50:
        return 'medium'
    return 'large'

# np.vectorize approach
classify_v = np.vectorize(classify_size)
df['size_class'] = classify_v(df['price'].values)
print(df[['price', 'size_class']])

Milloin apply() on oikea valinta

Apply on oikea työkalu, kun: (1) logiikka edellyttää haarautumista useiden sarakearvojen perusteella samanaikaisesti; (2) funktio kutsuu ulkoista APIa tai tietokantaa jokaisella rivillä (eli suoritus on väistämättä peräkkäinen); (3) funktio jäsentää monimutkaisen merkkijonon, kuten soluun tallennetun JSON-objektin; tai (4) funktio palauttaa muuttuvan pituisen objektin, kuten listan. Kaikissa muissa tapauksissa suosikaa vektoroituja operaatioita nopeuden ja luettavuuden vuoksi.

import json

# Parse a JSON metadata column row by row
df['metadata'] = ['{"color": "red"}', '{"color": "blue"}', '{}', '{"color": "green"}']
df['color'] = df['metadata'].apply(lambda s: json.loads(s).get('color', 'unknown'))
print(df[['metadata', 'color']])

Pikatarkistus

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

Oppitunnin kertaus

Tässä oppitunnissa opitte: käyttämään apply(axis=0)-menetelmää saraketason mukautettujen tilastojen laskemiseen, käyttämään apply(axis=1)-menetelmää riveihin kohdistuvien laskutoimitusten tekemiseen useiden sarakkeiden tietojen avulla ja tunnistamaan tilanteet, joissa vektorisoituja vaihtoehtoja kannattaa suosia suorituskyvyn vuoksi. Seuraavaksi tutustumme apply()-menetelmän käyttöön GroupBy-käsittelyn kanssa monimutkaisia ryhmätason aggregointeja 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 ”apply() sarakkeille ja riveille” ilmainen?

Kyllä – oppitunnin ”apply() sarakkeille ja riveille” 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 ”apply() sarakkeille ja riveille”?

Käyttäkää DataFrame.apply()-menetelmää axis=0- ja axis=1-akseleilla suorittaaksenne mukautetun funktion jokaiselle sarakkeelle tai riville. 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 1/4.

Kuinka kauan ”apply() sarakkeille ja riveille”-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