मेरे पंडों के 'लागू' कार्य कई कॉलमों को संदर्भित करने के लिए क्यों नहीं है? [बन्द है]


239

निम्नलिखित डेटाफ्रेम के साथ कई स्तंभों का उपयोग करते समय मुझे पंडों के कार्य के साथ कुछ समस्याएं हैं

df = DataFrame ({'a' : np.random.randn(6),
                 'b' : ['foo', 'bar'] * 3,
                 'c' : np.random.randn(6)})

और निम्नलिखित समारोह

def my_test(a, b):
    return a % b

जब मैं इस फ़ंक्शन को लागू करने का प्रयास करता हूं:

df['Value'] = df.apply(lambda row: my_test(row[a], row[c]), axis=1)

मुझे त्रुटि संदेश मिलता है:

NameError: ("global name 'a' is not defined", u'occurred at index 0')

मुझे यह संदेश समझ में नहीं आया, मैंने नाम को ठीक से परिभाषित किया।

मैं इस मुद्दे पर किसी भी मदद की बहुत सराहना करता हूं

अपडेट करें

आपकी सहायता के लिए धन्यवाद। मैंने कोड के साथ वास्तव में कुछ सिंटैक्स गलतियां की हैं, सूचकांक को '' रखा जाना चाहिए। हालाँकि मुझे अभी भी एक ही समस्या मिलती है जैसे कि अधिक जटिल फ़ंक्शन का उपयोग करते हुए:

def my_test(a):
    cum_diff = 0
    for ix in df.index():
        cum_diff = cum_diff + (a - df['a'][ix])
    return cum_diff 

1
applyजितना संभव हो उतना उपयोग करने से बचें । यदि आप सुनिश्चित नहीं हैं कि आपको इसका उपयोग करने की आवश्यकता है, तो आप संभवतः नहीं। मेरा सुझाव है कि मुझे अपने कोड में पंडों को लागू करने () का उपयोग कब करना चाहिए?
cs95

यह सिंटैक्स त्रुटियों के बारे में है जो डेटाफ्रेम कॉलम का संदर्भ देता है, और फ़ंक्शन को तर्कों की आवश्यकता क्यों होती है। आपके दूसरे प्रश्न के अनुसार, फ़ंक्शन को my_test(a)यह नहीं पता है कि dfवह क्या है क्योंकि इसे एक तर्क के रूप में पारित नहीं किया गया था (जब तक कि dfयह वैश्विक नहीं माना जाता है, जो भयानक अभ्यास होगा)। आपको एक फ़ंक्शन के अंदर उन सभी मूल्यों को पारित करने की आवश्यकता होगी जो तर्कों (अधिमानतः क्रम में) के रूप में आवश्यक हैं, अन्यथा फ़ंक्शन को और कहां dfसे पता चलेगा ? इसके अलावा, वैश्विक चर के साथ लिपटे एक नाम स्थान में प्रोग्राम करना बुरा है, आप इस तरह की त्रुटियों को नहीं पकड़ेंगे।
smci

जवाबों:


379

लगता है आप ''अपनी स्ट्रिंग भूल गए ।

In [43]: df['Value'] = df.apply(lambda row: my_test(row['a'], row['c']), axis=1)

In [44]: df
Out[44]:
                    a    b         c     Value
          0 -1.674308  foo  0.343801  0.044698
          1 -2.163236  bar -2.046438 -0.116798
          2 -0.199115  foo -0.458050 -0.199115
          3  0.918646  bar -0.007185 -0.001006
          4  1.336830  foo  0.534292  0.268245
          5  0.976844  bar -0.773630 -0.570417

BTW, मेरी राय में, निम्नलिखित तरीका अधिक सुरुचिपूर्ण है:

In [53]: def my_test2(row):
....:     return row['a'] % row['c']
....:     

In [54]: df['Value'] = df.apply(my_test2, axis=1)

धन्यवाद, आप सही हैं मैं '' भूल गया। हालाँकि मेरे पास अभी भी एक ही मुद्दा एक अधिक जटिल फ़ंक्शन के साथ है। मैं उस के साथ आपकी मदद की बहुत सराहना करूंगा। साभार
एंडी

5
@Andy के बाद [53-54] आपको और अधिक जटिल कार्यों को लागू करने की अनुमति देता है।
एंडी हेडन

@ और आप अपने जटिल कार्य को [53] तरीके से परिभाषित कर सकते हैं।
वेटाकुओ

क्या सभी लागू रणनीतियाँ समान हैं? मैं पंडों के लिए नया हूं और हमेशा थोड़ा सा रहस्यपूर्ण पाया है, लेकिन [५३-५४] में आपकी रणनीति मेरे लिए समझने में आसान है (और उम्मीद है कि याद रखें) ... एक बड़ी मेज पर यह लागू करने के अन्य रूप के रूप में त्वरित है प्रस्तुत किया?
Whytheq

ऐसा क्यों है कि एक अलग विधि का निर्माण अधिक सुरुचिपूर्ण माना जाता है - यहां तक ​​कि छोटे तरीकों के लिए भी। मैं 7 वर्षों से अजगर में महत्वपूर्ण परियोजनाएं कर रहा हूं, लेकिन संभवतः pythonistaइस एक सहित कुछ दृष्टिकोणों के कारण इसे कभी नहीं माना जाएगा ।
javadba

33

यदि आप केवल (कॉलम ए)% (कॉलम बी) की गणना करना चाहते हैं, तो आपको इसकी आवश्यकता नहीं है apply, बस इसे सीधे करें:

In [7]: df['a'] % df['c']                                                                                                                                                        
Out[7]: 
0   -1.132022                                                                                                                                                                    
1   -0.939493                                                                                                                                                                    
2    0.201931                                                                                                                                                                    
3    0.511374                                                                                                                                                                    
4   -0.694647                                                                                                                                                                    
5   -0.023486                                                                                                                                                                    
Name: a

16
मुझे पता है, कई कॉलमों में एक फ़ंक्शन लागू करने में मेरी समस्या को दिखाने के लिए यह सिर्फ एक उदाहरण है
एंडी

18

मान लें कि हम DataFrame df के कॉलम 'a' और 'b' में 'add5' फंक्शन लगाना चाहते हैं

def add5(x):
    return x+5

df[['a', 'b']].apply(add5)

आपका कोड स्निपेट आज़माते समय मुझे निम्न त्रुटि हो रही है। TypeError: ('str होना चाहिए, int नहीं', 'index b पर हुआ') क्या आप उस पर गौर कर सकते हैं।
debaonline4u

आपके डेटाफ्रेम का कॉलम b एक स्ट्रिंग प्रकार या ऑब्जेक्ट प्रकार का कॉलम है, यह एक पूर्णांक स्तंभ होना चाहिए जिसमें एक संख्या हो।
मिर_ मुर्तज़ा

क्या केवल असाइनमेंट के बाद ही बदलाव लागू नहीं होंगे?
S.aad

11

उपरोक्त सभी सुझाव काम करते हैं, लेकिन यदि आप चाहते हैं कि आपकी गणना अधिक कुशल हो, तो आपको संख्यात्मक वेक्टर ऑपरेशन (जैसा कि यहां बताया गया है) का लाभ उठाना चाहिए ।

import pandas as pd
import numpy as np


df = pd.DataFrame ({'a' : np.random.randn(6),
             'b' : ['foo', 'bar'] * 3,
             'c' : np.random.randn(6)})

उदाहरण 1: साथ लूपिंग pandas.apply():

%%timeit
def my_test2(row):
    return row['a'] % row['c']

df['Value'] = df.apply(my_test2, axis=1)

सबसे धीमी गति से चलने में 7.49 गुना अधिक समय लगा। इसका मतलब यह हो सकता है कि एक मध्यवर्ती परिणाम कैश किया जा रहा है। 1000 लूप, सर्वश्रेष्ठ 3: 481 loop प्रति लूप

उदाहरण 2: वेक्टराइज़ करें का उपयोग कर pandas.apply():

%%timeit
df['a'] % df['c']

सबसे धीमी गति से चलाने में 458.85 गुना अधिक समय लगा। इसका मतलब यह हो सकता है कि एक मध्यवर्ती परिणाम कैश किया जा रहा है। 10000 लूप, सर्वश्रेष्ठ 3: 70.9। प्रति लूप

उदाहरण 3: सुन्न सरणियों का उपयोग करते हुए वेक्टर करें:

%%timeit
df['a'].values % df['c'].values

सबसे धीमी गति से चलने में 7.98 गुना अधिक समय लगा। इसका मतलब यह हो सकता है कि एक मध्यवर्ती परिणाम कैश किया जा रहा है। 100000 लूप, 3 का सर्वश्रेष्ठ: 6.39 प्रति लूप

अतः अफीम के उपयोग से वेक्टरिंग ने परिमाण के लगभग दो आदेशों द्वारा गति में सुधार किया।


बड़ी संख्याओं के लिए परिणाम और भी नाटकीय रूप से बदलते हैं, जैसे 10K के साथ 6 की जगह, मुझे क्रमशः 248 एमएस, 332 µs, 263 atically मिलते हैं। तो दोनों सदिश समाधान एक दूसरे के बहुत करीब हैं, लेकिन गैर-वेक्टरित समाधान 1000 गुना धीमा है। (अजगर
-३.९

3

यह पिछले समाधान के समान है लेकिन मैंने फ़ंक्शन को df.apply में ही परिभाषित किया है:

df['Value'] = df.apply(lambda row: row['a']%row['c'], axis=1)

2

मैंने ऊपर चर्चा की गई तीनों की तुलना दी है।

मूल्यों का उपयोग करना

% समयगत df ['मान'] = df [[a ’]। मान% df ['c’] मान।

139 loops 91 1.91 mean प्रति लूप (मतलब। एसटीडी। 7 रन के देव, 10000 लूप प्रत्येक)।

मूल्यों के बिना

% समयगत df ['मान'] = df ['a]]% df [' c ’] 

216 means 86 1.86 mean प्रति लूप (मतलब। एसटीडी। 7 रन का देवता, प्रत्येक 1000 लूप)

फ़ंक्शन लागू करें

% timeit df ['मान'] = df.apply (लंबो पंक्ति: पंक्ति [’a]]% पंक्ति [% c’], अक्ष = १)

474 loops 7 5.07 means प्रति लूप (मतलब dev एसटीडी देव। 7 रन, 1000 लूप)।

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