Załóżmy, że mam ramkę danych pandy df
:
Chcę obliczyć średnią kolumnową ramki danych.
To jest łatwe:
df.apply(average)
następnie zakres mądry kolumny max (col) - min (col). To znowu jest łatwe:
df.apply(max) - df.apply(min)
Teraz dla każdego elementu chcę odjąć średnią z jego kolumny i podzielić przez zakres jego kolumny. Nie wiem, jak to zrobić
Każda pomoc / wskazówki są bardzo mile widziane.
A
iB
wejdź w skład większego czynnika grupowania, który chcesz normalizować oddzielnie odC
iD
.Jeśli nie masz nic przeciwko zaimportowaniu
sklearn
biblioteki, polecam metodę omówioną na tym blogu.import pandas as pd from sklearn import preprocessing data = {'score': [234,24,14,27,-74,46,73,-18,59,160]} cols = data.columns df = pd.DataFrame(data) df min_max_scaler = preprocessing.MinMaxScaler() np_scaled = min_max_scaler.fit_transform(df) df_normalized = pd.DataFrame(np_scaled, columns = cols) df_normalized
źródło
np_scaled = min_max_scaler.fit_transform(df.score.astype(float).values.reshape(-1, 1))
Możesz użyć
apply
do tego i jest trochę schludniej:import numpy as np import pandas as pd np.random.seed(1) df = pd.DataFrame(np.random.randn(4,4)* 4 + 3) 0 1 2 3 0 9.497381 0.552974 0.887313 -1.291874 1 6.461631 -6.206155 9.979247 -0.044828 2 4.276156 2.002518 8.848432 -5.240563 3 1.710331 1.463783 7.535078 -1.399565 df.apply(lambda x: (x - np.mean(x)) / (np.max(x) - np.min(x))) 0 1 2 3 0 0.515087 0.133967 -0.651699 0.135175 1 0.125241 -0.689446 0.348301 0.375188 2 -0.155414 0.310554 0.223925 -0.624812 3 -0.484913 0.244924 0.079473 0.114448
Działa również dobrze
groupby
, jeśli wybierzesz odpowiednie kolumny:df['grp'] = ['A', 'A', 'B', 'B'] 0 1 2 3 grp 0 9.497381 0.552974 0.887313 -1.291874 A 1 6.461631 -6.206155 9.979247 -0.044828 A 2 4.276156 2.002518 8.848432 -5.240563 B 3 1.710331 1.463783 7.535078 -1.399565 B df.groupby(['grp'])[[0,1,2,3]].apply(lambda x: (x - np.mean(x)) / (np.max(x) - np.min(x))) 0 1 2 3 0 0.5 0.5 -0.5 -0.5 1 -0.5 -0.5 0.5 0.5 2 0.5 0.5 0.5 -0.5 3 -0.5 -0.5 -0.5 0.5
źródło
Nieznacznie zmodyfikowane z: Python Pandas Dataframe: Normalizacja danych między 0,01 a 0,99? ale z niektórych komentarzy wynika, że jest to istotne (przepraszam, jeśli uważane za ponowne przesłanie ...)
Chciałem, aby dostosowana normalizacja w tym regularnym percentylu danych lub z-score nie była odpowiednia. Czasami wiedziałem, jakie są możliwe maksymalne i minimalne wartości populacji, i dlatego chciałem zdefiniować ją inaczej niż moja próbka, inny punkt środkowy lub cokolwiek! Może to być często przydatne do przeskalowania i normalizowania danych dla sieci neuronowych, w których możesz potrzebować wszystkich danych wejściowych od 0 do 1, ale niektóre dane mogą wymagać skalowania w bardziej dostosowany sposób ... ponieważ percentyle i standardowe wartości zakładają pokrycie próbek populacji, ale czasami wiemy, że to nieprawda. Było to również dla mnie bardzo przydatne podczas wizualizacji danych w heatmapach. Zbudowałem więc funkcję niestandardową (użyłem dodatkowych kroków w kodzie tutaj, aby uczynić ją jak najbardziej czytelną):
def NormData(s,low='min',center='mid',hi='max',insideout=False,shrinkfactor=0.): if low=='min': low=min(s) elif low=='abs': low=max(abs(min(s)),abs(max(s)))*-1.#sign(min(s)) if hi=='max': hi=max(s) elif hi=='abs': hi=max(abs(min(s)),abs(max(s)))*1.#sign(max(s)) if center=='mid': center=(max(s)+min(s))/2 elif center=='avg': center=mean(s) elif center=='median': center=median(s) s2=[x-center for x in s] hi=hi-center low=low-center center=0. r=[] for x in s2: if x<low: r.append(0.) elif x>hi: r.append(1.) else: if x>=center: r.append((x-center)/(hi-center)*0.5+0.5) else: r.append((x-low)/(center-low)*0.5+0.) if insideout==True: ir=[(1.-abs(z-0.5)*2.) for z in r] r=ir rr =[x-(x-0.5)*shrinkfactor for x in r] return rr
To zajmie serię pand, a nawet tylko listę i znormalizuje ją do określonych niskich, środkowych i wysokich punktów. istnieje również współczynnik kurczenia się! aby umożliwić Ci skalowanie danych z dala od punktów końcowych 0 i 1 (musiałem to zrobić łącząc mapy kolorów w matplotlib: Pojedynczy pcolormesh z więcej niż jedną mapą kolorów używającą Matplotlib ) Więc prawdopodobnie zobaczysz jak działa kod, ale zasadniczo mówię, że mają wartości [-5,1,10] w próbie, ale chcą znormalizować w oparciu o zakres od -7 do 7 (więc wszystko powyżej 7, nasze „10” jest traktowane jako 7) z punktem środkowym równym 2, ale zmniejsz ją, aby pasowała do mapy kolorów 256 RGB:
#In[1] NormData([-5,2,10],low=-7,center=1,hi=7,shrinkfactor=2./256) #Out[1] [0.1279296875, 0.5826822916666667, 0.99609375]
Może również wywrócić dane na drugą stronę ... może się to wydawać dziwne, ale uznałem to za przydatne do mapowania ciepła. Powiedzmy, że chcesz mieć ciemniejszy kolor dla wartości bliższych 0, a nie hi / low. Możesz utworzyć mapę cieplną w oparciu o znormalizowane dane, gdzie insideout = True:
#In[2] NormData([-5,2,10],low=-7,center=1,hi=7,insideout=True,shrinkfactor=2./256) #Out[2] [0.251953125, 0.8307291666666666, 0.00390625]
Zatem teraz „2”, które jest najbliżej środka, zdefiniowane jako „1”, jest wartością najwyższą.
W każdym razie pomyślałem, że moja aplikacja jest odpowiednia, jeśli chcesz przeskalować dane w inny sposób, który może mieć przydatne aplikacje.
źródło
Oto jak to robisz z podziałem na kolumny:
[df[col].update((df[col] - df[col].min()) / (df[col].max() - df[col].min())) for col in df.columns]
źródło