Oczywiście można tworzyć bardzo proste operacje na kolumnach - czyli wykorzystanie klasy series z pandas
bardzo wygodne do przekształceń jednej kolumny
natomiast nie sprawdza się podczas zmieniania całej serii kolumn
df['Sales'] = df['Sales'] * 100 # przykładowa operacja na kolumnie - przemnożenie przez 100# oczywiście można dodać nową kolumnędf['SalesDistribution'] = df['Sales'] / df['Sales'].sum()
Z kolei metoda eval() pozwala na bardzo wydajne przekształcanie danych wykorzystując wyrażenie, które
działa na kolumnach - bardzo kompaktowy zapis, szczególnie przy skomplikowanych obliczeniach
jest wydajne, zalecane do pracy z dużymi tabelami
ze względu na formę tekstową łatwo o błędy - brak podkreślania syntaxu
można używać @ lub f{} do przekazywania zmiennych środowiskowych
inplace=True pozwala na nadpisanie istniejącej ramki danych, domyślnie False
obsługuje również metody, stosując je na kolumnach
# Utworzenie nowej kolumny dzięki inplace=Truedf.eval('NetValue = (Sales - Discount) * (1 - .23)', inplace=True)# Metoda ze zmienną środowiskową, tym razem nie zmieni danych, jedynie wyświetli wynik (inplace=False)tax = 1 - .23df.eval('Net Value = (Sales - Discount) * @tax')df.eval(f'Net Value = (Sales - Discount) * {tax}')# I z użyciem metody...df.eval('SalesDistribution = Sales / Sales.sum()')
Do przekształceń o charakterze piepline, najlepiej stosować metodęassign()
bardzo dobre do wielu przekształceń
wykorzystując lambda można odwoływać się do wcześniej utworzonych kolumn - w innym wypadku odwołanie się w drugim argumencie do kolumny wynikowej z pierwszego argumentu będzie skutkować błędem
konstruktor wyrażeń posiada standardową składnie - bardzo intuicyjne
działa z grupby - metodą grupowania kolumn
tax=(1-.23)# Podstawowe przekształceniadf=df.assign(Profit = (df['Sales'] - df['Discount']) * tax)df=df.assign(Profit = lambda x: (x['Sales'] - x['Discount']) * tax) # użycie lambdy# Pipeline z wykorzystaniem lambdy w celu odwołania się do wcześniejszego wyniku# wykorzystanie piepline wymaga nawiasów wokół całego wyrażenia( df:=df # := powoduje, że wynik jest zarówno przypisany, jak i wyświetlony w konsoli .assign(SalesAfterDiscount = df['Sales'] - df['Discount']) .assign( Profit = lambda x: x['SalesAfterDiscount'] * tax, TaxPaid = lambda x: x['Sales'] * (1-tax) ))
Grupowanie
W przypadku bardziej zaawansowanych obliczeń na grupach, można zastosować kombinację
groupby() apply() i assign() z lambdą
groupby() grupuje kolumny, np, groupby('Product') lub dla wielu groupby(['Product' 'Region'])
argument as_index pozwala na utworzenie nowego indexu, z którego składają się użyte zmienne, domyślniej True
utworzony index można zrzucić używając metody reset_index(drop=True)
apply() stosuje dla każdej grupy zadane przekształcenie
assign() odwołuje się do tabeli utworzonej w lambda - dzięki temu może pracować na zgrupowanej tabeli
# Przypisanie nowych wartości, nie tworzy indexu( df:=df.groupby(['Region', 'Product'], as_index=False).apply( lambda x: x.assign( MeanSales = (x['Sales'] * 100).mean(), # przykładowe obliczenie MedianSales = x['Sales'].median(), q2Sales = x['Sales'].quantile(.25) ).round(2) ))# A tak wygląda z indexemdf.groupby(['Region', 'Product'], as_index=True).apply( lambda x: x.assign( MeanSales = (x['Sales'] * 100).mean(), # przykładowe obliczenie MedianSales = x['Sales'].median(), q2Sales = x['Sales'].quantile(.25) ).round(2))# można też ręcznie utworzyć klaster przypominający indexdf.groupby(['Region', 'Product'], as_index=True).apply( lambda x: x.assign( Cluster = 'Region: ' + x['Region'] + ' Selling: ' + x['Product'] ))
Jeżeli skomplikowanie assign() nie jest wymagane, można uprościć proces stosując transform()
w tym wypadku tworzymy groupby, a następnie wyciągamy z niego agregowaną kolumnę
# średnia sprzedaży dla każdego regionudf = df.groupby(['Region'])['Sales'].transform('mean')# średnia sprzedaży dla regionu i produktudf = df.groupby(['Region', 'Product'])['Sales'].transform('mean')