Pandalarda verileri normalleştirin


131

Pandalar veri çerçevem ​​olduğunu varsayalım df:

Bir veri çerçevesinin sütun bazında ortalamasını hesaplamak istiyorum.

Bu kolay:

df.apply(average) 

daha sonra sütun bilge aralığı max (col) - min (col). Bu yine çok kolay:

df.apply(max) - df.apply(min)

Şimdi her eleman için sütununun ortalamasını çıkarmak ve sütununun aralığına bölmek istiyorum. Bunu nasıl yapacağımdan emin değilim

Herhangi bir yardım / işaretçi çok takdir edilmektedir.

Yanıtlar:


225
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

Bir alt kümeyi normalleştirmek istiyorsanız bunu yapmanın bir yolu var mı? Bu satırı Say Ave Bsize ayrı normalleştirmek istediklerini daha büyük bir gruplaşma faktörünün parçasıdır Cve D.
Amyunimus

Alt kümeyi seçin ve daha önce olduğu gibi hesaplayın. Verilerin nasıl indeksleneceği ve seçileceği hakkında pandas.pydata.org/pandas-docs/stable/indexing.html adresine bakın
Wouter Overmeire

17
Değerlerinizin> 0 olması gerekiyorsa: df_norm = (df - df.min ()) / (df.max () - df.min ())
Dayvid Oliveira

1
0 ile 1 arasındaki değerleri elde etmek için ilk parantez içindeki df.mean () yerine df_norm = (df - df.min ()) / (df.max () - df.min ()) olmalıdır
jnPy

2
Veri çerçevenizde bazı sütunlarda dizeler varsa, bu yanıta
netskink

73

sklearnKütüphaneyi içe aktarmanın bir sakıncası yoksa , bu blogda anlatılan yöntemi tavsiye ederim .

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

2
blog gönderisinin bağlantısı kesildi. çalışan birinin var mı
marts

3
Birime göre normalleştirilmiş veri oluşturmak için karşılık gelen yöntem StandardScaler olarak adlandırılır.
abeboparebop

Başka bir yerde benzer bir çözüm buldum. Sorun, np_scaled kısmında, 2D dizi beklenirken bir hata gösteriyordu, ancak giriş 1D dizidir ve reshape (-1,1) kullanmamızı tavsiye etti. Bunu yeniden şekillendirme olarak nasıl çözüleceğine dair bir fikriniz de işe yaramıyor.
2017

Hangi numpy & sklearn sürümüyle çalıştığınıza bağlı olarak uyarılar alabilirsiniz, ancak genel olarak bu işe yaramalıdır np_scaled = min_max_scaler.fit_transform(df.score.astype(float).values.reshape(-1, 1))
yaramalıdır

33

Bunun için kullanabilirsiniz applyve biraz daha temiz:

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

Ayrıca, groupbyilgili sütunları seçerseniz , iyi çalışır :

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

2

Şuradan biraz değiştirildi: Python Pandas Dataframe: 0.01 ile 0.99 arasında veriler normalleştirilsin mi?ancak bazı yorumlardan konuyla ilgili olduğunu düşündü (yine de bir yeniden yayın olarak kabul edilirse özür dilerim ...)

Verinin düzenli yüzdelik diliminde özelleştirilmiş normalleştirme istedim veya z-skoru yeterli değildi. Bazen popülasyonun uygulanabilir maksimum ve minimumunun ne olduğunu biliyordum ve bu nedenle onu örneklem dışında veya farklı bir orta nokta veya her neyse dışında tanımlamak istedim! Bu genellikle 0 ile 1 arasında tüm girdileri isteyebileceğiniz sinir ağları için verileri yeniden ölçeklendirmek ve normalleştirmek için yararlı olabilir, ancak verilerinizin bir kısmının daha özelleştirilmiş bir şekilde ölçeklenmesi gerekebilir ... nüfus, ama bazen bunun doğru olmadığını biliyoruz. Isı haritalarında verileri görselleştirirken de benim için çok faydalı oldu. Bu yüzden özel bir işlev oluşturdum (mümkün olduğunca okunabilir hale getirmek için buradaki kodda ekstra adımlar kullandım):

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

Bu, bir pandalar dizisini veya hatta sadece bir listeyi alacak ve belirttiğiniz alt, orta ve yüksek noktalara göre normalleştirecektir. ayrıca bir küçültme faktörü var! verileri 0 ve 1 uç noktalarından uzak bir yere ölçeklendirmenize izin vermek için (bunu matplotlib'de renk haritalarını birleştirirken yapmak zorunda kaldım: Matplotlib kullanarak birden fazla renk haritasıyla tek pcolormesh ) Bu nedenle, kodun nasıl çalıştığını muhtemelen görebilirsiniz, ancak temelde bir örnekte [-5,1,10] değerlerine sahiptir, ancak -7 ila 7 aralığına göre normalize etmek istiyorsanız (yani 7'nin üzerindeki herhangi bir şey, "10 "'umuz etkili bir şekilde 7 olarak kabul edilir) 2 orta noktası ile, ancak 256 RGB renk haritasına sığacak şekilde küçültün:

#In[1]
NormData([-5,2,10],low=-7,center=1,hi=7,shrinkfactor=2./256)
#Out[1]
[0.1279296875, 0.5826822916666667, 0.99609375]

Ayrıca verilerinizi tersyüz edebilir ... bu tuhaf görünebilir, ancak ısı haritalama için yararlı buldum. Yüksek / düşük yerine 0'a yakın değerler için daha koyu bir renk istediğinizi varsayalım. İçeride = Doğru olduğunda normalleştirilmiş verilere dayalı olarak ısı haritası yapabilirsiniz:

#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]

Şimdi merkeze en yakın olan "2", "1" olarak tanımlanan en yüksek değerdir.

Her neyse, sizin için yararlı uygulamalar olabilecek başka şekillerde verileri yeniden ölçeklendirmek istiyorsanız başvurumun alakalı olduğunu düşündüm.


Tüm if / else ifadelerini işlevli bir sözlükle değiştirebilirsiniz . O zaman biraz daha temiz görünüyor.
Roald

bu oldukça temiz, bir dahaki sefere bunu aklımda tutacağım, teşekkürler!
Vlox

0

Bunu sütun bazında şu şekilde yaparsınız:

[df[col].update((df[col] - df[col].min()) / (df[col].max() - df[col].min())) for col in df.columns]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.