पांडा डेटा फ्रेम के सामान्य कॉलम


226

मेरे पास पंडों में एक डेटाफ्रेम है जहां प्रत्येक कॉलम में अलग-अलग मूल्य सीमा है। उदाहरण के लिए:

df:

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

किसी भी विचार मैं इस डेटाफ्रेम के कॉलम को कैसे सामान्य कर सकता हूं जहां प्रत्येक मान 0 और 1 के बीच है?

मेरा वांछित उत्पादन है:

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
वहाँ एक लागू समारोह है, जैसे फ्रेम .apply (एफ, अक्ष = 1) जहां च एक ऐसा फ़ंक्शन है जो एक पंक्ति के साथ कुछ करता है ...
tschm

1
सामान्यीकरण सबसे उपयुक्त शब्दांकन नहीं हो सकता है, क्योंकि स्किट-लर्न डॉक्यूमेंटेशन इसे " यूनिट के मानदंड के लिए अलग-अलग नमूनों को स्केल करने की प्रक्रिया" के रूप में परिभाषित करता है (यानी यदि मैं इसे सही तरीके से प्राप्त करता हूं तो पंक्ति)।
स्किप्पी ले ग्रैंड गौरू

मुझे यह नहीं मिलता है, क्यों min_max स्केलिंग को सामान्यीकरण माना जाता है! सामान्य को शून्य और भिन्नता के साथ सामान्य वितरण के अर्थ में अर्थ मिला है। 1.
ओवरफ्लो पुलिस

यदि आप 2020 में या बाद में इस प्रश्न पर जा रहे हैं, तो @Poudel के उत्तर को देखें, यदि आप पांडा बनाम स्केलेर का उपयोग करते हैं तो आपको सामान्य करने के अलग-अलग उत्तर मिलते हैं।
भीषण पौडेल

@ पोडेल इस ddofतर्क के कारण है ?
फाफ्रोस्ट

जवाबों:


223

आप डेटा को सामान्य बनाने के लिए पैकेज स्केलेर और इसके संबद्ध प्रीप्रोसेसिंग उपयोगिताओं का उपयोग कर सकते हैं।

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)

अधिक जानकारी के लिए प्रीप्रोसेसिंग डेटा पर स्किकिट-लर्न डॉक्यूमेंटेशन देखें : एक सीमा तक सुविधाओं को स्केल करना।


46
मुझे लगता है कि इससे कॉलम नामों से छुटकारा मिल जाएगा, जो उन कारणों में से एक हो सकता है जो ऑप पहली बार डेटाफ्रेम का उपयोग कर रहे हैं।
21

47
यह पंक्तियों को सामान्य करेगा और कॉलम नहीं, जब तक आप इसे पहले स्थानांतरित नहीं करते हैं। वह करने के लिए जो क्यू पूछता है:pd.DataFrame(min_max_scaler.fit_transform(df.T), columns=df.columns, index=df.index)
होब्स

26
कॉलम नाम रखने के लिए @pietz, इस पोस्ट को देखें । मूल रूप से अंतिम पंक्ति को बदलें,df=pandas.DataFrame(x_scaled, columns=df.columns)
ijoseph

5
@ हब्स यह सही नहीं है। सैंडमैन का कोड कॉलम-वार और प्रति-कॉलम सामान्य करता है। यदि आप संक्रमण करते हैं तो आपको गलत परिणाम मिलता है।
पीटीज़्यूरिच

8
@petezurich ऐसा लगता है कि सैंडमैन या प्रवीण ने अपने कोड को सही किया। ); दुर्भाग्य से, यह संभव नहीं है सही टिप्पणी करने के लिए है
hobs

397

पंडों का उपयोग करके एक आसान तरीका : (यहां मैं सामान्य सामान्यीकरण का उपयोग करना चाहता हूं)

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

न्यूनतम-अधिकतम सामान्यीकरण का उपयोग करने के लिए:

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

संपादित करें: कुछ चिंताओं को दूर करने के लिए, यह कहने की आवश्यकता है कि पंडों ने ऊपर दिए गए कोड में कॉलोमन-वार फ़ंक्शन को स्वचालित रूप से लागू किया है।


16
मैं यह पसंद है। यह छोटा है, यह अभिव्यंजक है और यह शीर्ष लेख की जानकारी को संरक्षित करता है। लेकिन मुझे लगता है कि आपको हर में मिनिस्टर को घटाना होगा।
पिटीज १६'१

6
मुझे नहीं लगता कि यह गलत है। मेरे लिए खूबसूरती से काम करता है - मुझे नहीं लगता कि इसका मतलब () और एसटीडी () को काम करने के लिए एक डेटाफ़्रेम वापस करना होगा और आपका त्रुटि संदेश यह नहीं कहता है कि उन्हें डेटाफ़्रेम नहीं होना एक समस्या है।
स्ट्रैंडटैचेस

24
यह कॉलम सामान्यीकरण नहीं है। यह पूरे मैट्रिक्स को सामान्य कर रहा है, जो गलत परिणाम प्रदान करेगा।
नगुई अल

6
मेरे लिए भी खूबसूरती से काम किया। @Nuauaial आप इसे एक सुस्पष्ट मैट्रिक्स पर आज़मा रहे होंगे जिस स्थिति में परिणाम वही होगा जो आपने कहा था। लेकिन पंडों के डेटाफ्रेम के लिए, न्यूनतम, अधिकतम ... उपाय डिफ़ॉल्ट रूप से कॉलम-वार लागू होते हैं।
अनुगामी

1
मुझे यह भी पसंद है
इसहाक सिम

51

इस पोस्ट के आधार पर: /stats/70801/how-to-normalize-data-to-0-1-range

आप निम्न कार्य कर सकते हैं:

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

आपको इस बारे में चिंता करने की ज़रूरत नहीं है कि आपके मूल्य नकारात्मक हैं या सकारात्मक। और मान 0 और 1 के बीच अच्छी तरह से फैला होना चाहिए।


8
न्यूनतम और अधिकतम मान समान होने पर सावधान रहें, आपके हर का मान 0 है और आपको NaN मान मिलेगा।
ह्रषिकेश धूमल

36

आपकी समस्या वास्तव में स्तंभों पर अभिनय करने वाला एक सरल परिवर्तन है:

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

frame.apply(f, axis=0)

या इससे भी अधिक:

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

2
lambdaएक सबसे अच्छा है :-)
अबू शोएब

4
क्या यह प्रश्न = कॉलम वाइज नॉर्मलाइज़ेशन के बाद से एक्सिस = 1 नहीं माना जाता है?
नगुई अल

नहीं है, से डॉक्स : axis [...] 0 or 'index': apply function to each column। डिफ़ॉल्ट वास्तव में है axis=0इसलिए इस वन-लाइनर को और भी छोटा लिखा जा सकता है :-) धन्यवाद @tschm
15:11 बजे jorijnsmit

30

यदि आप स्केलेर पैकेज का उपयोग करना पसंद करते हैं, तो आप पंडों का उपयोग करके कॉलम और इंडेक्स नाम रख सकते हैं loc:

from sklearn.preprocessing import MinMaxScaler

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

27

सादगी खुबसुरत है:

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

महान और मेरी राय में सबसे अच्छा समाधान!
मकीज ए। बेदर्नज

6
ध्यान दें, कि ओपी ने [०.१.१] श्रेणी और इस समाधान को [१.१.१] सीमा के लिए कहा है। इस सरणी [-10, 10] के साथ प्रयास करें।
अलेक्जेंडर सोसनोवशेंको

3
@AlexanderSosnovshchenko वास्तव में नहीं। तुलसी मूसा मान रहे हैं कि ओपी का मैट्रिक्स हमेशा गैर-नकारात्मक होता है, इसीलिए उन्होंने यह समाधान दिया है। यदि कुछ कॉलम में नकारात्मक प्रविष्टि है, तो यह कोड [-1,1] सीमा तक सामान्य नहीं होता है। इसे सरणी [-5, 10] के साथ आज़माएँ। df["A"] = (df["A"]-df["A"].min()) / (df["A"].max()-df["A"].min())
सीना

सरल और स्पष्ट
joshi123

शायद और भी सरल: df /= df.max()- लक्ष्य मानकर व्यक्तिगत रूप से प्रत्येक स्तंभ को सामान्य करना है।
n1k31t4

24

आप उन स्तंभों की सूची बना सकते हैं जिन्हें आप सामान्य करना चाहते हैं

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

आपके पंडों के डेटाफ़्रेम अब केवल आपके इच्छित कॉलम पर सामान्यीकृत हैं


हालाँकि , यदि आप विपरीत चाहते हैं, तो उन स्तंभों की एक सूची चुनें, जिन्हें आप सामान्य नहीं करना चाहते हैं, आप बस सभी स्तंभों की एक सूची बना सकते हैं और उन गैर-वांछित लोगों को हटा सकते हैं

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

मुझे लगता है कि पांडा में ऐसा करने का एक बेहतर तरीका बस है

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

संपादित करें यदि आपके डेटा फ़्रेम में नकारात्मक संख्याएं मौजूद हैं, तो आपको इसके बजाय उपयोग करना चाहिए

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

1
यदि किसी कॉलम के सभी मान शून्य हैं तो यह काम नहीं करेगा
ahajib

अधिकतम मान द्वारा वर्तमान मूल्य को विभाजित करने से आपको एक सामान्य स्थिति नहीं
मिलेगी

मैं सहमत हूं, लेकिन यह वही है जो ओटी के लिए पूछ रहा था (उसका उदाहरण देखें)
Daniele

11

सैंडमैन और प्रवीण द्वारा दिया गया समाधान बहुत अच्छा है। इसके साथ एकमात्र समस्या यह है कि यदि आपके डेटा फ्रेम के अन्य कॉलम में श्रेणीबद्ध चर हैं तो इस पद्धति में कुछ समायोजन की आवश्यकता होगी।

इस प्रकार की समस्या का मेरा समाधान निम्नलिखित है:

 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
यह उत्तर उपयोगी है क्योंकि इंटरनेट पर अधिकांश उदाहरण सभी स्तंभों पर एक स्केलर लागू करते हैं, जबकि यह वास्तव में उस स्थिति को संबोधित करता है जहां एक स्केलर, मिनमैक्सस्कलर कहते हैं, सभी कॉलमों पर लागू नहीं होना चाहिए।
डिमॉन्गॉल्म

10

अजगर में विभिन्न मानकीकरण का उदाहरण।

संदर्भ के लिए इस विकिपीडिया लेख को देखें: https://en.wikipedia.org/wiki/Unbiased_estimation_of_standard_deviation

उदाहरण डेटा

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

पांडा का उपयोग करके सामान्यीकरण (निष्पक्ष अनुमान देता है)

जब हम सामान्य करते हैं तो हम औसत को घटाते हैं और मानक विचलन द्वारा विभाजित करते हैं।

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

स्केलेर का उपयोग करके सामान्यीकरण (पंडों से अलग, पक्षपाती अनुमान देता है)

यदि आप ऐसा ही करते हैं, तो आपको sklearnDIFFERENT आउटपुट मिल जाएगा!

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

क्या स्केलेर का बायस्ड अनुमान मशीन लर्निंग को कम शक्तिशाली बनाता है?

नहीं।

Sklearn.preprocessing.scale के आधिकारिक दस्तावेज में कहा गया है कि मशीन सीखने वाले एल्गोरिदम के प्रदर्शन को प्रभावित करने के लिए पक्षपाती आकलनकर्ता का उपयोग करना UNLIKELY है और हम सुरक्षित रूप से उनका उपयोग कर सकते हैं।

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 स्केलिंग के बारे में क्या?

मिनमैक्स स्केलिंग में कोई मानक विचलन गणना नहीं है। तो परिणाम पंडों और स्किटिट-लर्न दोनों में समान है।

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

आप कुछ स्तंभों को सामान्यीकृत करना चाहते हैं और अन्य कुछ प्रतिगमन कार्यों की तरह अपरिवर्तित हो सकते हैं, जो डेटा लेबल या श्रेणीबद्ध कॉलम अपरिवर्तित हैं, इसलिए मैं आपको यह pythonic तरीका सुझाता हूं (यह @shg और @Cina उत्तरों का एक संयोजन है):

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

यह केवल सरल गणित है। जवाब नीचे के रूप में सरल होना चाहिए।

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)

पांडा के दस्तावेज से, DataFrame संरचना खुद के लिए एक ऑपरेशन (फ़ंक्शन) लागू कर सकती है।

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

DataFrame के इनपुट अक्ष के साथ कार्य करता है। फ़ंक्शन के लिए पास की गई ऑब्जेक्ट श्रृंखला ऑब्जेक्ट हैं जिसमें या तो डेटाफ्रेम का इंडेक्स है (अक्ष = 0) या कॉलम (अक्ष = 1)। वापसी प्रकार इस बात पर निर्भर करता है कि क्या पास किए गए फ़ंक्शन समुच्चय, या कम तर्क यदि DataFrame खाली है।

आप DataFrame को संचालित करने के लिए एक कस्टम फ़ंक्शन लागू कर सकते हैं।


2
यह स्पष्ट करना अच्छा होगा कि आपका कोड ओपी समस्या क्यों हल करता है, इसलिए लोग आपके कोड को कॉपी करने के बजाय रणनीति को अनुकूलित कर सकते हैं। कृपया पढ़ें मैं एक अच्छा उत्तर कैसे लिखूं?
मि। टी। टी।

2

निम्न फ़ंक्शन Z स्कोर की गणना करता है:

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

सूची बोध का उपयोग करते हुए आप इसे कॉलम-वार कैसे करते हैं:

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

1

आप बस इस तरह pandas.DataFrame.transform 1 फ़ंक्शन का उपयोग कर सकते हैं :

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

यदि सभी मान नकारात्मक हैं, तो यह समाधान काम नहीं करेगा। [-1, -2, -3] पर विचार करें। हम -1 से विभाजित करते हैं, और अब हमारे पास [1,2,3] है।
डेव लियू


0

इसे आप एक लाइन में कर सकते हैं

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

यह प्रत्येक स्तंभ के लिए माध्य लेता है और फिर इसे प्रत्येक पंक्ति से (मतलब) घटाता है (विशेष स्तंभ का मतलब केवल इसकी पंक्ति से घटाता है) और केवल मतलब से विभाजित करता है। अंत में, हम जो प्राप्त करते हैं वह सामान्यीकृत डेटा सेट है।


0

पंडों डिफ़ॉल्ट रूप से कॉलम सामान्यीकरण करते हैं। नीचे दिए गए कोड का प्रयास करें।

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

आउटपुट मान 0 और 1 की सीमा में होंगे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.