पांडा अन्य कॉलमों के मानों के आधार पर नए कॉलम बनाते हैं / कई कॉलम, पंक्ति-वार का फ़ंक्शन लागू करते हैं


316

मैं (यह एक करता है, तो-और कुछ सीढ़ी का उपयोग करता है) इन छह कॉलम (करने के लिए अपने कस्टम समारोह लागू करना चाहते हैं ERI_Hispanic, ERI_AmerInd_AKNatv, ERI_Asian, ERI_Black_Afr.Amer, ERI_HI_PacIsl, ERI_Whiteमेरी dataframe की प्रत्येक पंक्ति में)।

मैंने अन्य प्रश्नों से अलग तरीकों की कोशिश की है, लेकिन फिर भी अपनी समस्या के लिए सही उत्तर नहीं खोज पाया। इसका महत्वपूर्ण टुकड़ा यह है कि यदि व्यक्ति को हिस्पैनिक के रूप में गिना जाता है तो उन्हें किसी और चीज के रूप में नहीं गिना जा सकता है। यहां तक ​​कि अगर उनके पास एक और जातीयता स्तंभ में "1" है, तो उन्हें अभी भी हिस्पैनिक नहीं दो या अधिक दौड़ के रूप में गिना जाता है। इसी तरह, यदि सभी ईआरआई कॉलम का योग 1 से अधिक है, तो उन्हें दो या अधिक दौड़ के रूप में गिना जाता है और एक अद्वितीय जातीयता (हिस्पैनिक को छोड़कर) के रूप में नहीं गिना जा सकता है। उम्मीद है कि यह समझ में आता है। किसी भी प्रकार की सहायता सराहनीय होगी।

इसका लगभग प्रत्येक पंक्ति के माध्यम से लूप के लिए करना पसंद है और यदि प्रत्येक रिकॉर्ड एक कसौटी पर खरा उतरता है तो उन्हें एक सूची में जोड़ दिया जाता है और मूल से समाप्त कर दिया जाता है।

नीचे दी गई डेटाफ्रेम से मुझे एसक्यूएल में निम्नलिखित युक्ति के आधार पर एक नए कॉलम की गणना करने की आवश्यकता है:

============================ CRITERIA ========================= =======

IF [ERI_Hispanic] = 1 THEN RETURN Hispanic
ELSE IF SUM([ERI_AmerInd_AKNatv] + [ERI_Asian] + [ERI_Black_Afr.Amer] + [ERI_HI_PacIsl] + [ERI_White]) > 1 THEN RETURN Two or More
ELSE IF [ERI_AmerInd_AKNatv] = 1 THEN RETURN A/I AK Native
ELSE IF [ERI_Asian] = 1 THEN RETURN Asian
ELSE IF [ERI_Black_Afr.Amer] = 1 THEN RETURN Black/AA
ELSE IF [ERI_HI_PacIsl] = 1 THEN RETURN Haw/Pac Isl.”
ELSE IF [ERI_White] = 1 THEN RETURN White

टिप्पणी: यदि हिस्पैनिक के लिए ईआरआई ध्वज सच है (1), तो कर्मचारी को "हिस्पैनिक" के रूप में वर्गीकृत किया गया है।

टिप्पणी: यदि 1 से अधिक गैर-हिस्पैनिक ईआरआई ध्वज सत्य हैं, तो "दो या अधिक" लौटाएं

==================== DATAFRAME =============================

     lname          fname       rno_cd  eri_afr_amer    eri_asian   eri_hawaiian    eri_hispanic    eri_nat_amer    eri_white   rno_defined
0    MOST           JEFF        E       0               0           0               0               0               1           White
1    CRUISE         TOM         E       0               0           0               1               0               0           White
2    DEPP           JOHNNY              0               0           0               0               0               1           Unknown
3    DICAP          LEO                 0               0           0               0               0               1           Unknown
4    BRANDO         MARLON      E       0               0           0               0               0               0           White
5    HANKS          TOM         0                       0           0               0               0               1           Unknown
6    DENIRO         ROBERT      E       0               1           0               0               0               1           White
7    PACINO         AL          E       0               0           0               0               0               1           White
8    WILLIAMS       ROBIN       E       0               0           1               0               0               0           White
9    EASTWOOD       CLINT       E       0               0           0               0               0               1           White

आपका विशेष कार्य केवल एक लंबा है, अगर-और सीढ़ी जहां कुछ चर के मान दूसरों पर प्राथमिकता लेते हैं। इसे हार्डवेयर इंजीनियरिंग क्षेत्र में प्राथमिकता-डिकोडर कहा जाएगा ।
smci

जवाबों:


407

ठीक है, इसके दो चरण - पहला एक फ़ंक्शन लिखना है जो अनुवाद आप चाहते हैं - मैंने आपके छद्म कोड के आधार पर एक उदाहरण दिया है:

def label_race (row):
   if row['eri_hispanic'] == 1 :
      return 'Hispanic'
   if row['eri_afr_amer'] + row['eri_asian'] + row['eri_hawaiian'] + row['eri_nat_amer'] + row['eri_white'] > 1 :
      return 'Two Or More'
   if row['eri_nat_amer'] == 1 :
      return 'A/I AK Native'
   if row['eri_asian'] == 1:
      return 'Asian'
   if row['eri_afr_amer']  == 1:
      return 'Black/AA'
   if row['eri_hawaiian'] == 1:
      return 'Haw/Pac Isl.'
   if row['eri_white'] == 1:
      return 'White'
   return 'Other'

आप इस पर जाना चाह सकते हैं, लेकिन ऐसा लगता है कि ट्रिक - ध्यान दें कि फ़ंक्शन में जाने वाले पैरामीटर को "पंक्ति" लेबल वाली श्रृंखला ऑब्जेक्ट माना जाता है।

अगला, फ़ंक्शन को लागू करने के लिए पांडा में लागू फ़ंक्शन का उपयोग करें - जैसे

df.apply (lambda row: label_race(row), axis=1)

अक्ष = 1 स्पेसियर पर ध्यान दें, इसका मतलब है कि आवेदन एक स्तंभ स्तर के बजाय एक पंक्ति में किया जाता है। परिणाम यहाँ हैं:

0           White
1        Hispanic
2           White
3           White
4           Other
5           White
6     Two Or More
7           White
8    Haw/Pac Isl.
9           White

यदि आप उन परिणामों से खुश हैं, तो इसे फिर से चलाएँ, परिणाम को अपने मूल डेटाफ़्रेम में एक नए कॉलम में सहेजते हुए।

df['race_label'] = df.apply (lambda row: label_race(row), axis=1)

परिणामी डेटाफ़्रेम इस तरह दिखता है (नए कॉलम को देखने के लिए दाईं ओर स्क्रॉल करें):

      lname   fname rno_cd  eri_afr_amer  eri_asian  eri_hawaiian   eri_hispanic  eri_nat_amer  eri_white rno_defined    race_label
0      MOST    JEFF      E             0          0             0              0             0          1       White         White
1    CRUISE     TOM      E             0          0             0              1             0          0       White      Hispanic
2      DEPP  JOHNNY    NaN             0          0             0              0             0          1     Unknown         White
3     DICAP     LEO    NaN             0          0             0              0             0          1     Unknown         White
4    BRANDO  MARLON      E             0          0             0              0             0          0       White         Other
5     HANKS     TOM    NaN             0          0             0              0             0          1     Unknown         White
6    DENIRO  ROBERT      E             0          1             0              0             0          1       White   Two Or More
7    PACINO      AL      E             0          0             0              0             0          1       White         White
8  WILLIAMS   ROBIN      E             0          0             1              0             0          0       White  Haw/Pac Isl.
9  EASTWOOD   CLINT      E             0          0             0              0             0          1       White         White

69
बस एक ध्यान दें: यदि आप केवल पंक्ति को अपने कार्य में खिला रहे हैं, तो आप बस कर सकते हैं:df.apply(label_race, axis=1)
पॉल एच

1
अगर मैं एक और पंक्ति के साथ कुछ ऐसा ही करना चाहता था तो क्या मैं उसी फ़ंक्शन का उपयोग कर सकता था? उदाहरण के लिए, परिणामों से, अगर ['race_label'] == "व्हाइट" वापसी 'व्हाइट' और इसी तरह। लेकिन अगर ['race_label'] == 'अज्ञात' ['rno_defined'] कॉलम से मान लौटाता है। मुझे लगता है कि वही फ़ंक्शन काम करेगा, लेकिन मुझे यह पता नहीं लग सकता है कि दूसरे कॉलम से मान कैसे प्राप्त करें।
डेव

2
आप एक नया फ़ंक्शन लिख सकते हैं, जो 'race_label' फ़ील्ड को देखता है, और एक नए फ़ील्ड में परिणाम भेजता है, या - और मुझे लगता है कि यह इस मामले में बेहतर हो सकता है, मूल फ़ंक्शन को संपादित करें, अंतिम return 'Other'पंक्ति को बदलकर return row['rno_defined']जिसे करना चाहिए उन मामलों में उस कॉलम से मूल्य को प्रतिस्थापित करें जहां पर / फिर बयानों के सेट को एक मैच नहीं मिलता है (यानी वर्तमान में, जहां आप 'अन्य' देखें)।
थॉमस किम्बर

9
आप सरलीकृत कर सकते हैं: df.apply(lambda row: label_race (row),axis=1)सेdf.apply(label_race, axis=1)
user48956

5
नए संस्करणों में, यदि आपको 'SettingWithCopyWarning' मिलता है, तो आपको 'असाइन' पद्धति को देखना चाहिए। देखें: stackoverflow.com/a/12555510/3015186
np8

218

चूँकि यह 'दूसरों से नया स्तंभ' के लिए पहला Google परिणाम है, यहाँ एक सरल उदाहरण दिया गया है:

import pandas as pd

# make a simple dataframe
df = pd.DataFrame({'a':[1,2], 'b':[3,4]})
df
#    a  b
# 0  1  3
# 1  2  4

# create an unattached column with an index
df.apply(lambda row: row.a + row.b, axis=1)
# 0    4
# 1    6

# do same but attach it to the dataframe
df['c'] = df.apply(lambda row: row.a + row.b, axis=1)
df
#    a  b  c
# 0  1  3  4
# 1  2  4  6

यदि आप प्राप्त करते हैं SettingWithCopyWarningतो आप इसे इस तरह भी कर सकते हैं:

fn = lambda row: row.a + row.b # define a function for the new column
col = df.apply(fn, axis=1) # get column data with an index
df = df.assign(c=col.values) # assign values to column 'c'

स्रोत: https://stackoverflow.com/a/12555510/243392

और यदि आपके कॉलम के नाम में रिक्त स्थान शामिल हैं, तो आप इस तरह से वाक्यविन्यास का उपयोग कर सकते हैं:

df = df.assign(**{'some column name': col.values})

और यहाँ आवेदन के लिए प्रलेखन है , और असाइन करना है


1
संक्षिप्त उत्तर, आवश्यक के लिए आसुत!
फ्रोड एसेलसन

1
SettingWithCopyWarningजब मैं कर रहा हूँ, तो df['c'] = df.apply(lambda row: row.a + row.b, axis=1) क्या मैं यहाँ एक वास्तविक मुद्दा हूँ, या मुझे इसकी चिंता नहीं करनी चाहिए?
नैट

2
@ क्या मुझे वह चेतावनी कभी नहीं मिली - शायद यह डेटाफ्रेम में डेटा पर निर्भर करता है? लेकिन मैंने 2017 से एक और जवाब के आधार पर जवाब में संशोधन किया।
ब्रायन बर्न्स

56

उपरोक्त उत्तर पूरी तरह से मान्य हैं, लेकिन एक सदिश समाधान मौजूद है, के रूप में numpy.select। यह आपको शर्तों को परिभाषित करने की अनुमति देता है, फिर उन परिस्थितियों के लिए आउटपुट को परिभाषित करता है, उपयोग करने की तुलना में बहुत अधिक कुशलता से apply:


सबसे पहले, शर्तों को परिभाषित करें:

conditions = [
    df['eri_hispanic'] == 1,
    df[['eri_afr_amer', 'eri_asian', 'eri_hawaiian', 'eri_nat_amer', 'eri_white']].sum(1).gt(1),
    df['eri_nat_amer'] == 1,
    df['eri_asian'] == 1,
    df['eri_afr_amer'] == 1,
    df['eri_hawaiian'] == 1,
    df['eri_white'] == 1,
]

अब, इसी आउटपुट को परिभाषित करें:

outputs = [
    'Hispanic', 'Two Or More', 'A/I AK Native', 'Asian', 'Black/AA', 'Haw/Pac Isl.', 'White'
]

अंत में, का उपयोग कर numpy.select:

res = np.select(conditions, outputs, 'Other')
pd.Series(res)

0           White
1        Hispanic
2           White
3           White
4           Other
5           White
6     Two Or More
7           White
8    Haw/Pac Isl.
9           White
dtype: object

क्यों numpy.selectइस्तेमाल किया जाना चाहिए apply? यहाँ कुछ प्रदर्शन जाँच हैं:

df = pd.concat([df]*1000)

In [42]: %timeit df.apply(lambda row: label_race(row), axis=1)
1.07 s ± 4.16 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [44]: %%timeit
    ...: conditions = [
    ...:     df['eri_hispanic'] == 1,
    ...:     df[['eri_afr_amer', 'eri_asian', 'eri_hawaiian', 'eri_nat_amer', 'eri_white']].sum(1).gt(1),
    ...:     df['eri_nat_amer'] == 1,
    ...:     df['eri_asian'] == 1,
    ...:     df['eri_afr_amer'] == 1,
    ...:     df['eri_hawaiian'] == 1,
    ...:     df['eri_white'] == 1,
    ...: ]
    ...:
    ...: outputs = [
    ...:     'Hispanic', 'Two Or More', 'A/I AK Native', 'Asian', 'Black/AA', 'Haw/Pac Isl.', 'White'
    ...: ]
    ...:
    ...: np.select(conditions, outputs, 'Other')
    ...:
    ...:
3.09 ms ± 17 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

उपयोग करने numpy.selectसे हमें काफी बेहतर प्रदर्शन मिलता है, और डेटा बढ़ने पर ही विसंगति बढ़ेगी।


7
यह समाधान बहुत कम है। मुझे पता था कि मैं आवेदन के साथ भी कुछ ऐसा कर सकता हूं लेकिन एक विकल्प की तलाश में था क्योंकि मुझे हजारों फाइलों के लिए उस ऑपरेशन को करना होगा। तो खुशी है कि मुझे आपकी पोस्ट मिल गई।
एमएक्स

मुझे कुछ समान बनाने में परेशानी हो रही है। मुझे "एक श्रृंखला का सत्य मूल्य अस्पष्ट है ..." त्रुटि संदेश। मेरा कोड कान्सास_सिटी = ['एनडी ’,, एसडी’, C एनई ’, Kansas केएस’,' एमएन ’, 'आईए’,' एमओ ’] स्थितियां = [डीएफ_मेरज [_ स्टेट_लफा’] कंसास -सिटी में] आउटपुट = [' कैनसस सिटी '] df_merge [' क्षेत्र '] = np.select (शर्तें, आउटपुट,' अन्य ') क्या कोई मदद कर सकता है?
शॉन श्रेयर

2
यह स्वीकृत उत्तर होना चाहिए। अन्य ठीक हैं, लेकिन एक बार जब आप बड़े डेटा में काम कर रहे होते हैं, तो यह एक ही काम करता है, और यह आश्चर्यजनक तेजी से काम करता है।
theProletariat

29

.apply()पहले पैरामीटर के रूप में एक फ़ंक्शन में लेता है; में पास label_raceइतनी के रूप में समारोह:

df['race_label'] = df.apply(label_race, axis=1)

किसी फंक्शन में पास होने के लिए आपको लैम्ब्डा फंक्शन करने की जरूरत नहीं है।


12

इसे इस्तेमाल करे,

df.loc[df['eri_white']==1,'race_label'] = 'White'
df.loc[df['eri_hawaiian']==1,'race_label'] = 'Haw/Pac Isl.'
df.loc[df['eri_afr_amer']==1,'race_label'] = 'Black/AA'
df.loc[df['eri_asian']==1,'race_label'] = 'Asian'
df.loc[df['eri_nat_amer']==1,'race_label'] = 'A/I AK Native'
df.loc[(df['eri_afr_amer'] + df['eri_asian'] + df['eri_hawaiian'] + df['eri_nat_amer'] + df['eri_white']) > 1,'race_label'] = 'Two Or More'
df.loc[df['eri_hispanic']==1,'race_label'] = 'Hispanic'
df['race_label'].fillna('Other', inplace=True)

ओ / पी:

     lname   fname rno_cd  eri_afr_amer  eri_asian  eri_hawaiian  \
0      MOST    JEFF      E             0          0             0   
1    CRUISE     TOM      E             0          0             0   
2      DEPP  JOHNNY    NaN             0          0             0   
3     DICAP     LEO    NaN             0          0             0   
4    BRANDO  MARLON      E             0          0             0   
5     HANKS     TOM    NaN             0          0             0   
6    DENIRO  ROBERT      E             0          1             0   
7    PACINO      AL      E             0          0             0   
8  WILLIAMS   ROBIN      E             0          0             1   
9  EASTWOOD   CLINT      E             0          0             0   

   eri_hispanic  eri_nat_amer  eri_white rno_defined    race_label  
0             0             0          1       White         White  
1             1             0          0       White      Hispanic  
2             0             0          1     Unknown         White  
3             0             0          1     Unknown         White  
4             0             0          0       White         Other  
5             0             0          1     Unknown         White  
6             0             0          1       White   Two Or More  
7             0             0          1       White         White  
8             0             0          0       White  Haw/Pac Isl.  
9             0             0          1       White         White 

के .locबजाय का उपयोग करें apply

यह वैश्वीकरण में सुधार करता है।

.loc साधारण तरीके से काम करता है, स्थिति के आधार पर मुखौटा पंक्तियां, फ्रीज पंक्तियों के लिए मान लागू करता है।

अधिक जानकारी के लिए, .loc डॉक्स पर जाएं

प्रदर्शन मेट्रिक्स:

स्वीकृत उत्तर:

def label_race (row):
   if row['eri_hispanic'] == 1 :
      return 'Hispanic'
   if row['eri_afr_amer'] + row['eri_asian'] + row['eri_hawaiian'] + row['eri_nat_amer'] + row['eri_white'] > 1 :
      return 'Two Or More'
   if row['eri_nat_amer'] == 1 :
      return 'A/I AK Native'
   if row['eri_asian'] == 1:
      return 'Asian'
   if row['eri_afr_amer']  == 1:
      return 'Black/AA'
   if row['eri_hawaiian'] == 1:
      return 'Haw/Pac Isl.'
   if row['eri_white'] == 1:
      return 'White'
   return 'Other'

df=pd.read_csv('dataser.csv')
df = pd.concat([df]*1000)

%timeit df.apply(lambda row: label_race(row), axis=1)

1.15 s 15 46.5 एमएस प्रति लूप (मतलब dev एसटीडी। 7 रन का देवता, 1 लूप प्रत्येक)

मेरा प्रस्तावित उत्तर:

def label_race(df):
    df.loc[df['eri_white']==1,'race_label'] = 'White'
    df.loc[df['eri_hawaiian']==1,'race_label'] = 'Haw/Pac Isl.'
    df.loc[df['eri_afr_amer']==1,'race_label'] = 'Black/AA'
    df.loc[df['eri_asian']==1,'race_label'] = 'Asian'
    df.loc[df['eri_nat_amer']==1,'race_label'] = 'A/I AK Native'
    df.loc[(df['eri_afr_amer'] + df['eri_asian'] + df['eri_hawaiian'] + df['eri_nat_amer'] + df['eri_white']) > 1,'race_label'] = 'Two Or More'
    df.loc[df['eri_hispanic']==1,'race_label'] = 'Hispanic'
    df['race_label'].fillna('Other', inplace=True)
df=pd.read_csv('s22.csv')
df = pd.concat([df]*1000)

%timeit label_race(df)

24.7 एमएस .7 1.7 एमएस प्रति लूप (मतलब। एसटीडी। 7 रन का। प्रत्येक छोर पर 10 लूप)

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