Pandalarım neden birden çok sütuna başvuruda bulunan 'uygula' işlevi çalışmıyor? [kapalı]


239

Aşağıdaki dataframe ile birden çok sütun kullanırken, Pandalar uygulama işleviyle ilgili bazı sorunlar var

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

ve aşağıdaki fonksiyon

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

Bu işlevi ile uygulamaya çalıştığınızda:

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

Hata mesajını alıyorum:

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

Bu mesajı anlamıyorum, adı doğru tanımladım.

Bu konuda herhangi bir yardım için çok minnettar olurum

Güncelleme

Yardımınız için teşekkürler. Gerçekten kod ile bazı sözdizimi hataları yaptım, dizin koymak gerekir ''. Ancak yine de aynı sorunu daha karmaşık bir işlevi kullanarak alıyorum:

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

1
applyMümkün olduğunca kullanmaktan kaçının . Kullanmanız gerektiğinden emin değilseniz muhtemelen kullanmıyorsunuzdur. Kodumda ne zaman panda uygula () kullanmak istersem? .
cs95

Bu, bir veri çerçevesi sütununa gönderme yapan sözdizimi hatalarıyla ilgilidir ve işlevlerin neden bağımsız değişkenlere ihtiyacı vardır. İkinci sorunuzla ilgili olarak, bu işlev my_test(a), dfbir argüman olarak aktarılmadığından ne olduğunu bilmiyor (eğer dfküresel olması gerekiyorsa, bu korkunç bir uygulamadır). Bir fonksiyonun içinde ihtiyacınız olan tüm değerleri argüman olarak (tercihen sırayla) iletmeniz gerekir, aksi takdirde fonksiyon başka nereden dfgeldiğini nasıl bilir ? Ayrıca, global değişkenlerle dolu bir ad alanında program yapmak kötü bir uygulamadır, böyle hataları yakalamazsınız.
smci

Yanıtlar:


379

Dizeni unuttun ''.

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, bence, aşağıdaki şekilde daha zarif:

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

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

Teşekkürler, haklısın '' i unuttum. Ancak yine de daha karmaşık bir işlevle aynı sorunu yaşıyorum. Bununla ilgili yardımınızı çok takdir ediyorum. Teşekkürler
Andy

5
@Andy'yi takip ederek [53-54] daha karmaşık işlevler uygulamanıza olanak tanır.
Andy Hayden

@Andy karmaşık işlevinizi In [53] yolu gibi tanımlayabilirsiniz.
bekleme

uygulanan tüm stratejiler aynı mıdır? Pandalar için yeniyim ve her zaman biraz esrarengiz uygulamayı bulduk, ancak [53-54] 'deki stratejiniz benim için kolay (ve umarım hatırlıyorum) ... büyük bir tabloda diğer başvuru şekli kadar hızlı sunulan?
whytheq

Ayrı bir yöntem oluşturmanın neden küçük yöntemler için bile daha zarif olduğu düşünülmektedir. 7 yıldır python'da önemli projeler yapıyorum ama muhtemelen bunun da pythonistadahil olduğu bazı perspektifler nedeniyle asla düşünülmeyecek .
javadba

33

Yalnızca (sütun a)% (sütun b) 'yi hesaplamak istiyorsanız, ihtiyacınız applyyoktur, doğrudan yapın:

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
Biliyorum, sadece birden fazla sütuna bir işlev uygulamadaki sorunumu göstermek için bir örnek
Andy

18

Diyelim ki DataFrame df'nin 'a' ve 'b' sütunlarına add5 fonksiyonunu uygulamak istiyoruz

def add5(x):
    return x+5

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

Kod snippet'inizi denerken aşağıdaki hatayı alıyorum. TypeError: ('int olmalıdır, str değil', 'indeks b'de meydana geldi') lütfen buna bakabilirsiniz.
debaonline4u

Veri çerçevenizin b sütunu bir dize türü veya nesne türü sütunudur, bir sayı ile eklenecek bir tamsayı sütunu olmalıdır.
Mir_Murtaza

Değişiklikler yalnızca görevlendirildikten sonra geçerli olmaz mı?
S.aad

11

Yukarıdaki tüm öneriler işe yarıyor, ancak hesaplamalarınızın daha verimli olmasını istiyorsanız, (burada belirtildiği gibi) numpy vektör işlemlerinden yararlanmalısınız .

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)})

Örnek 1: İle döngü pandas.apply():

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

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

En yavaş koşu en hızlıdan 7,49 kat daha uzun sürdü. Bu, ara sonucun önbelleğe alındığı anlamına gelebilir. 1000 döngü, döngü başına en iyi 3: 481 µs

Örnek 2: Şunları kullanarak vektörleştirin pandas.apply():

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

En yavaş koşu en hızlıdan 458.85 kat daha uzun sürdü. Bu, ara sonucun önbelleğe alındığı anlamına gelebilir. 10000 döngü, en iyi 3: döngü başına 70,9 µs

Örnek 3: Numpy dizileri kullanarak vektörleştirin:

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

En yavaş koşu en hızlı koşunun 7.98 kat daha uzun sürdü. Bu, ara sonucun önbelleğe alındığı anlamına gelebilir. 100000 döngü, en iyisi 3: döngü başına 6,39 µs

Bu nedenle, numpy dizileri kullanarak vektörleştirme hızı neredeyse iki büyüklük düzeyinde geliştirdi.


Sonuçlar büyük sayılar için daha da çarpıcı bir şekilde değişir, örneğin 6'yı 10K ile değiştirmek, sırasıyla 248 ms, 332 µs, 263 µs elde ediyorum. Dolayısıyla her iki vektörleştirilmiş çözelti birbirine çok daha yakındır, ancak vektörleştirilmemiş çözelti 1000 kat daha yavaştır. (python-
3.7'de

3

Bu önceki çözüm ile aynıdır, ancak df.apply kendisi işlevi tanımladım:

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

2

Yukarıda tartışılan üçünün de karşılaştırmasını verdim.

Değerleri kullanma

% timeit df ['değer'] = df ['a']. değerler% df ['c']. değerler

Her döngü için 139 µs ± 1.91 µs (ortalama 7 std. ± 7 çalışma, her biri 10000 döngü)

Değerler olmadan

% timeit df ['değer'] = df ['a']% df ['c'] 

Loop başına 216 µs ± 1.86 µs (ortalama 7 std dev., Her biri 1000 loop)

Uygula işlevi

% timeit df ['Değer'] = df.apply (lambda satırı: satır ['a']% satır ['c'], eksen = 1)

Döngü başına 474 µs ± 5.07 µs (ortalama 7 std dev., Her biri 1000 döngü)

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.