Pandalar veri çerçevesinin sütunlarını normalleştirme


230

Her sütun farklı değer aralığına sahip pandalar içinde bir veri çerçevesi var. Örneğin:

df:

A     B   C
1000  10  0.5
765   5   0.35
800   7   0.09

Her bir değerin 0 ile 1 arasında olduğu bu veri çerçevesinin sütunlarını nasıl normalleştirebilirim?

İstediğim çıktı:

A     B    C
1     1    1
0.765 0.5  0.7
0.8   0.7  0.18(which is 0.09/0.5)

1
bir uygulama işlevi vardır, örneğin frame.apply (f, eksen = 1) burada f, satır ile bir şey yapan bir
işlevdir

1
Normalleştirme en uygun anlatım olmayabilir, çünkü scikit-learn belgeleri bunu " tek tek örnekleri birim normuna sahip olarak ölçekleme işlemi" olarak tanımlar (yani, doğru şekilde alırsam satır satır).
Skippy le Grand Gourou

Anlamıyorum, neden min_max ölçekleme normalleştirme olarak kabul edilir! normal, ortalama sıfır ve varyans 1 ile normal dağılım anlamında bir anlam ifade
etmelidir

Bu soruyu 2020 veya daha sonra ziyaret ediyorsanız, @Poudel tarafından verilen cevaba bakın, pandalar vs sklearn kullanıyorsanız normalleştirmenin farklı cevabı alırsınız.
Bhishan Poudel

@Poudel bu ddofargüman yüzünden mi?
fffrost

Yanıtlar:


224

Verileri normalleştirmek için sklearn paketini ve onunla ilişkili önişleme yardımcı programlarını kullanabilirsiniz.

import pandas as pd
from sklearn import preprocessing

x = df.values #returns a numpy array
min_max_scaler = preprocessing.MinMaxScaler()
x_scaled = min_max_scaler.fit_transform(x)
df = pd.DataFrame(x_scaled)

Daha fazla bilgi için önişleme verisi hakkındaki scikit-learn belgelerine bakın : özellikleri bir aralığa göre ölçeklendirme.


46
Ben bu op isimleri ilk etapta kullanmak nedenlerinden biri olabilir, sütun isimleri kurtulmak düşünüyorum.
17'de pietz

47
Bu, önce aktarmadığınız sürece sütunları değil satırları normalleştirir. : Q sorar ne yapacağınıpd.DataFrame(min_max_scaler.fit_transform(df.T), columns=df.columns, index=df.index)
ocak

26
@pietz sütun adlarını saklamak için bu gönderiye bakın . Temel olarak son satırı değiştirin,df=pandas.DataFrame(x_scaled, columns=df.columns)
ijoseph

5
@hobs Bu doğru değil. Sandman'ın kodu, sütun ve sütun başına normalleşir. Transpozisyon yaparsanız yanlış sonuç alırsınız.
petezurich

8
@petezurich Sandman veya Praveen kodlarını düzeltmiş gibi görünüyor. Ne yazık ki, yorumları düzeltmek mümkün değildir;)
ocaklar

399

Pandaları kullanarak kolay bir yol : (burada normal normalleştirme kullanmak istiyorum)

normalized_df=(df-df.mean())/df.std()

min-maks normalizasyonu kullanmak için:

normalized_df=(df-df.min())/(df.max()-df.min())

Düzenleme: Bazı endişeleri gidermek için, Pandalar yukarıdaki kodda otomatik olarak kolomn-bilge işlevi uyguladığını söylemek gerekir.


16
bunu beğendim. kısa, etkileyici ve başlık bilgisini koruyor. ama bence paydadaki min'i çıkarmanız gerekiyor.
17'de pietz

6
Bunun yanlış olduğunu düşünmüyorum. Benim için güzel çalışıyor - Bunun çalışması için mean () ve std () bir veri çerçevesi döndürmeniz gerektiğini düşünmüyorum ve hata mesajınız bir veri çerçevesi olmadıkları anlamına gelmiyor.
Strandtasche

24
bu sütun bazında normalleştirme değildir. bu tüm matrisi bir bütün olarak normalleştirerek yanlış sonuçlar verecektir.
Nguai al

7
Ayrıca benim için güzel çalıştı. @Nguaial bunu numpy matris üzerinde deniyor olabilirsiniz, bu durumda sonuç söylediğiniz gibi olacaktır. Ancak Pandalar veri çerçeveleri için, min, max, ... ölçüleri varsayılan olarak sütun bazında uygulanır.
Yardımcı

1
Ben de bunu seviyorum
Isaac Sim

51

Bu gönderiye dayanarak: /stats/70801/how-to-normalize-data-to-0-1-range

Aşağıdakileri yapabilirsiniz:

def normalize(df):
    result = df.copy()
    for feature_name in df.columns:
        max_value = df[feature_name].max()
        min_value = df[feature_name].min()
        result[feature_name] = (df[feature_name] - min_value) / (max_value - min_value)
    return result

Değerlerinizin negatif veya pozitif olup olmadığı konusunda endişelenmenize gerek yoktur. Ve değerler 0 ile 1 arasında güzel bir şekilde yayılmalıdır.


8
Min ve maks değerleri aynı olduğunda, payda 0 olduğunda dikkatli olun ve bir NaN değeri elde edersiniz.
Hrushikesh Dhumal

36

Sorununuz aslında sütunlara etki eden basit bir dönüşümdür:

def f(s):
    return s/s.max()

frame.apply(f, axis=0)

Veya daha da keskin:

   frame.apply(lambda x: x/x.max(), axis=0)

2
lambdaBiri :-) en iyisi
Abu Shoeb

4
soru sütun bilge normalizasyonu olduğundan bunun eksen = 1 olması gerekmez mi?
Nguai al

Hayır, gelen docs : axis [...] 0 or 'index': apply function to each column. Varsayılan aslında axis=0bu tek astar daha kısa yazılabilir :-) Teşekkürler @tschm.
jorijnsmit

30

Sklearn paketini kullanmak isterseniz, aşağıdaki locgibi pandaları kullanarak sütun ve dizin adlarını saklayabilirsiniz :

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler() 
scaled_values = scaler.fit_transform(df) 
df.loc[:,:] = scaled_values

27

Basit güzeldir:

df["A"] = df["A"] / df["A"].max()
df["B"] = df["B"] / df["B"].max()
df["C"] = df["C"] / df["C"].max()

Harika ve bence en iyi çözüm!
Maciej A. Bednarz

6
OP'nin [0..1] aralığını istediğini ve bu çözümün [-1..1] aralığına ölçeklendiğini unutmayın. Bunu [-10, 10] dizisiyle deneyin.
Alexander Sosnovshchenko

3
@AlexanderSosnovshchenko gerçekten değil. Basil Musa, OP'nin matrisinin her zaman negatif olmadığını varsayar, bu yüzden bu çözümü verdi. Bazı sütunlarda negatif giriş varsa, bu kod [-1,1] aralığına normalleşmez. [-5, 10] dizisiyle deneyin. Negatif değerlerle [0,1] 'e normalleşmenin doğru yolu df["A"] = (df["A"]-df["A"].min()) / (df["A"].max()-df["A"].min())
Cina'nın

basit VE açık
joshi123

Belki daha da basit: df /= df.max()- hedefin her sütunu ayrı ayrı normalleştirmek olduğunu varsayarsak.
n1k31t4

24

Normalleştirmek istediğiniz sütunların bir listesini oluşturabilirsiniz

column_names_to_normalize = ['A', 'E', 'G', 'sadasdsd', 'lol']
x = df[column_names_to_normalize].values
x_scaled = min_max_scaler.fit_transform(x)
df_temp = pd.DataFrame(x_scaled, columns=column_names_to_normalize, index = df.index)
df[column_names_to_normalize] = df_temp

Pandalar Veri Çerçeveniz artık yalnızca istediğiniz sütunlarda normalleştiriliyor


Ancak isterseniz, tersini , bu sütunların bir liste seçmek YAPMAYIN normalize etmek istiyorum, sadece tüm sütunların bir listesini oluşturmak ve dışı istenilen olanları kaldırabilirsiniz

column_names_to_not_normalize = ['B', 'J', 'K']
column_names_to_normalize = [x for x in list(df) if x not in column_names_to_not_normalize ]

11

Pandalarda bunu yapmanın daha iyi bir yolunun

df = df/df.max().astype(np.float64)

Düzenle Veri çerçevenizde negatif sayılar varsa bunun yerine

df = df/df.loc[df.abs().idxmax()].astype(np.float64)

1
Bir sütunun tüm değerlerinin sıfır olması durumunda bu çalışmaz
ahajib

güncel değerin maksimuma bölünmesi, min 0 olmadığı sürece size doğru bir normalizasyon
sağlamaz.

Kabul ediyorum, ama OT'nin istediği buydu (örneğine bakın)
Daniele

11

Sandman ve Praveen tarafından verilen çözüm çok iyi. Bununla ilgili tek sorun, veri çerçevenizin diğer sütunlarında kategorik değişkenleriniz varsa, bu yöntemin bazı ayarlamalar yapması gerekecektir.

Bu tür bir sorun için benim çözüm şu:

 from sklearn import preprocesing
 x = pd.concat([df.Numerical1, df.Numerical2,df.Numerical3])
 min_max_scaler = preprocessing.MinMaxScaler()
 x_scaled = min_max_scaler.fit_transform(x)
 x_new = pd.DataFrame(x_scaled)
 df = pd.concat([df.Categoricals,x_new])

2
Bu cevap faydalıdır, çünkü internetteki çoğu örnek tüm sütunlara bir ölçekleyici uygularken, bu aslında bir ölçekleyicinin, örneğin MinMaxScaler'ın tüm sütunlara uygulanmaması gerektiği durumu ele alır.
demongolem

10

Python'da farklı standardizasyon örnekleri.

Referans için bu wikipedia makalesine bakın: https://en.wikipedia.org/wiki/UnPrice_estimation_of_standard_deviation

Örnek Veriler

import pandas as pd
df = pd.DataFrame({
               'A':[1,2,3],
               'B':[100,300,500],
               'C':list('abc')
             })
print(df)
   A    B  C
0  1  100  a
1  2  300  b
2  3  500  c

Pandalar kullanarak normalleştirme (Tarafsız tahminler verir)

Normalleştirirken ortalamayı çıkarırız ve standart sapmaya böleriz.

df.iloc[:,0:-1] = df.iloc[:,0:-1].apply(lambda x: (x-x.mean())/ x.std(), axis=0)
print(df)
     A    B  C
0 -1.0 -1.0  a
1  0.0  0.0  b
2  1.0  1.0  c

Sklearn kullanarak normalleştirme (Pandalardan farklı, önyargılı tahminler verir)

Sizinle aynı şeyi sklearnyaparsanız FARKLI çıktı alırsınız!

import pandas as pd

from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()


df = pd.DataFrame({
               'A':[1,2,3],
               'B':[100,300,500],
               'C':list('abc')
             })
df.iloc[:,0:-1] = scaler.fit_transform(df.iloc[:,0:-1].to_numpy())
print(df)
          A         B  C
0 -1.224745 -1.224745  a
1  0.000000  0.000000  b
2  1.224745  1.224745  c

Önyargılı sklearn tahminleri Makine Öğrenimini Daha Az Güçlü Yapar mı?

HAYIR.

Sklearn.preprocessing.scale'nin resmi dokümantasyonu, eğimli tahmin ediciyi kullanmanın makine öğrenimi algoritmalarının performansını etkilemek için OLMADIĞINI ve bunları güvenle kullanabileceğimizi belirtmektedir.

From official documentation:
We use a biased estimator for the standard deviation,
equivalent to numpy.std(x, ddof=0). 
Note that the choice of ddof is unlikely to affect model performance.

MinMax Ölçeklendirme ne olacak?

MinMax ölçeğinde Standart Sapma hesaplaması yoktur. Sonuç hem pandalarda hem de scikit-öğrenmede aynıdır.

import pandas as pd
df = pd.DataFrame({
               'A':[1,2,3],
               'B':[100,300,500],
             })
(df - df.min()) / (df.max() - df.min())
     A    B
0  0.0  0.0
1  0.5  0.5
2  1.0  1.0


# Using sklearn
from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler() 
arr_scaled = scaler.fit_transform(df) 

print(arr_scaled)
[[0.  0. ]
 [0.5 0.5]
 [1.  1. ]]

df_scaled = pd.DataFrame(arr_scaled, columns=df.columns,index=df.index)
print(df_scaled)
     A    B
0  0.0  0.0
1  0.5  0.5
2  1.0  1.0

6

Bazı sütunların normalleştirilmesini ve diğerlerinin değişmesini, veri etiketlerinin veya kategorik sütunların değişmediği regresyon görevlerinin bazıları gibi değişmesini isteyebilirsiniz.

features_to_normalize = ['A', 'B', 'C']
# could be ['A','B'] 

df[features_to_normalize] = df[features_to_normalize].apply(lambda x:(x-x.min()) / (x.max()-x.min()))

5

Sadece basit bir matematik. Cevap aşağıdaki gibi basit olmalıdır.

normed_df = (df - df.min()) / (df.max() - df.min())

2
def normalize(x):
    try:
        x = x/np.linalg.norm(x,ord=1)
        return x
    except :
        raise
data = pd.DataFrame.apply(data,normalize)

Panda belgelerinden DataFrame yapısı kendisine bir işlem (işlev) uygulayabilir.

DataFrame.apply(func, axis=0, broadcast=False, raw=False, reduce=None, args=(), **kwds)

İşlevi DataFrame öğesinin giriş ekseni boyunca uygular. İşlevlere iletilen nesneler, DataFrame'in dizinine (eksen = 0) veya sütunlara (eksen = 1) sahip dizilerdir. Dönüş türü, iletilen işlevin toplanıp toplanmamasına veya DataFrame boşsa azaltma bağımsız değişkenine bağlıdır.

DataFrame'i çalıştırmak için özel bir işlev uygulayabilirsiniz.


2
Kodunuzun neden OP sorununu çözdüğünü açıklamak iyi olur, böylece insanlar sadece kodunuzu kopyalamak yerine stratejiyi uyarlayabilir. Lütfen İyi bir cevabı nasıl yazarım?
Bay T

2

Aşağıdaki işlev Z puanını hesaplar:

def standardization(dataset):
  """ Standardization of numeric fields, where all values will have mean of zero 
  and standard deviation of one. (z-score)

  Args:
    dataset: A `Pandas.Dataframe` 
  """
  dtypes = list(zip(dataset.dtypes.index, map(str, dataset.dtypes)))
  # Normalize numeric columns.
  for column, dtype in dtypes:
      if dtype == 'float32':
          dataset[column] -= dataset[column].mean()
          dataset[column] /= dataset[column].std()
  return dataset

2

Liste kavrayışını kullanarak bunu sütun şeklinde yapıyorsunuz:

[df[col].update((df[col] - df[col].min()) / (df[col].max() - df[col].min())) for col in df.columns]

1

Bu şekilde pandas.DataFrame.transform 1 işlevini şu şekilde kullanabilirsiniz:

df.transform(lambda x: x/x.max())

Tüm değerler negatifse bu çözüm çalışmaz. [-1, -2, -3] düşünün. -1'e bölüyoruz ve şimdi [1,2,3] var.
Dave Liu


0

Bunu tek bir satırda yapabilirsiniz

DF_test = DF_test.sub(DF_test.mean(axis=0), axis=1)/DF_test.mean(axis=0)

sütunun her biri için ortalama alır ve ardından her satırdan (ortalama) çıkarır (yalnızca belirli sütunun ortalaması satırından çıkarır) ve yalnızca ortalamaya böler. Son olarak, elde ettiğimiz şey normalleştirilmiş veri kümesidir.


0

Pandalar varsayılan olarak sütun normalleştirmesi yapar. Aşağıdaki kodu deneyin.

X= pd.read_csv('.\\data.csv')
X = (X-X.min())/(X.max()-X.min())

Çıkış değerleri 0 ve 1 aralığında olacaktır.

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.