Нормализовать данные в pandas
Предположим, что у меня есть кадр данных pandas df
:
Я хочу рассчитать среднее значение столбца кадра данных.
Это легко:
df.apply(average)
тогда диапазон столбцов max (col) - min (col). Это снова легко:
df.apply(max) - df.apply(min)
Теперь для каждого элемента я хочу вычесть его среднее значение столбца и делить на его диапазон столбцов. Я не уверен, как это сделать
Любая помощь/указатели очень ценится.
Ответы
Ответ 1
In [92]: df
Out[92]:
a b c d
A -0.488816 0.863769 4.325608 -4.721202
B -11.937097 2.993993 -12.916784 -1.086236
C -5.569493 4.672679 -2.168464 -9.315900
D 8.892368 0.932785 4.535396 0.598124
In [93]: df_norm = (df - df.mean()) / (df.max() - df.min())
In [94]: df_norm
Out[94]:
a b c d
A 0.085789 -0.394348 0.337016 -0.109935
B -0.463830 0.164926 -0.650963 0.256714
C -0.158129 0.605652 -0.035090 -0.573389
D 0.536170 -0.376229 0.349037 0.426611
In [95]: df_norm.mean()
Out[95]:
a -2.081668e-17
b 4.857226e-17
c 1.734723e-17
d -1.040834e-17
In [96]: df_norm.max() - df_norm.min()
Out[96]:
a 1
b 1
c 1
d 1
Ответ 2
Если вы не против импортировать библиотеку sklearn
, я бы порекомендовал метод, описанный в этом блоге.
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
Ответ 3
Вы можете использовать apply
для этого, и это немного опережает:
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
Кроме того, он отлично работает с groupby
, если вы выберете соответствующие столбцы:
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
Ответ 4
Немного изменен из: Python Pandas Dataframe: нормализовать данные между 0,01 и 0,99?, но из некоторых комментариев считается, что это релевантно (извините, если считать repost хотя...)
Мне нужна индивидуальная нормализация в том, что регулярный процентиль нулевой точки или z-балл был недостаточным. Иногда я знал, какие возможные макс и минимальные числа населения были, и поэтому хотел определить его, кроме моего образца, или другой середины, или что-то еще! Это часто может быть полезно для масштабирования и нормализации данных для нейронных сетей, где вам могут потребоваться все входы между 0 и 1, но некоторые из ваших данных могут нуждаться в масштабировании более индивидуальным образом... потому что процентили и stdevs предполагают, что ваши образцы охватывают население, но иногда мы знаем, что это неверно. Это было очень полезно для меня при визуализации данных в тепловых картах. Поэтому я создал пользовательскую функцию (здесь использовались дополнительные шаги в коде, чтобы сделать ее максимально читаемой):
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
Это займет серию Pandas или даже просто список и нормализует его до ваших низких, центральных и высоких точек. также есть коэффициент сжатия! чтобы вы могли масштабировать данные далеко от конечных точек 0 и 1 (мне приходилось делать это при объединении цветовых палитр в matplotlib: Одиночный pcolormesh с более чем одной цветовой схемой с использованием Matplotlib) Таким образом, вы можете увидеть, как работает код, но в основном говорят, что у вас есть значения [-5,1,10] в выборке, но вы хотите нормализовать на основе диапазона от -7 до 7 (так что ничего выше 7, наш "10" обрабатывается как 7 эффективно) с серединой 2, но уменьшает его, чтобы он соответствовал 256-битной цветовой карте:
#In[1]
NormData([-5,2,10],low=-7,center=1,hi=7,shrinkfactor=2./256)
#Out[1]
[0.1279296875, 0.5826822916666667, 0.99609375]
Он также может превратить ваши данные наизнанку... это может показаться странным, но я нашел его полезным для термоматеринга. Предположим, вам нужен более темный цвет для значений, близких к 0, а не hi/low. Вы можете нагревать карту на основе нормализованных данных, где inout = 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]
Итак, теперь "2", который ближе всего к центру, определяется как "1", является самым высоким значением.
В любом случае, я думал, что мое приложение имеет значение, если вы хотите перемасштабировать данные другими способами, которые могут иметь полезные приложения для вас.
Ответ 5
Если вы хотите нормализовать данные, вы должны использовать это простое решение
df = (df - df.min()) / (df.max() - df.min())
Ответ 6
Вот как вы делаете это по столбцам:
[df[col].update((df[col] - df[col].min()) / (df[col].max() - df[col].min())) for col in df.columns]