web-dev-qa-db-ja.com

複数の列を参照するPandasの「適用」関数が機能しないのはなぜですか?

次のデータフレームで複数の列を使用しているときに、Pandas適用機能に問題があります。

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 
207
Andy

文字列の''を忘れたようです。

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

ところで、私の考えでは、次の方法がよりエレガントです。

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

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

(列a)%(列b)を計算するだけの場合は、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
30
herrfz

関数add5をDataFrame dfの列 'a'と 'b'に適用したいとしましょう。

def add5(x):
    return x+5

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

上記の提案はすべてうまくいきますが、計算をもっと効率的にしたいのであれば、派手なベクトル演算 (ここで指摘) を利用する必要があります。

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 µs

例2:pandas.apply()を使ってベクトル化する:

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

最も遅い走行は最も速い走行より458.85倍長くかかりました。これは中間結果がキャッシュされていることを意味します。 10000ループ、最高3:ループあたり70.9 µs

例3:テンキー配列を使用してベクトル化する

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

最も遅い走行は最も速い走行よりも7.98倍長くかかりました。これは中間結果がキャッシュされていることを意味します。 100000ループ、最高3:ループあたり6.39 µs

そのため、テンキー配列を使用してベクトル化すると、速度が約2桁向上しました。

9
Blane

これは前の解決策と同じですが、私はdf.apply自体で関数を定義しました:

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

上記の3つすべてを比較しました。

値を使う

%timeit df ['値'] = df ['a']。値%df ['c']。値

1ループあたり139 µs±1.91 µs(7回の平均±標準偏差、各10000ループ)

値なし

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

1ループあたり216μs±1.86μs(7回の平均±標準偏差、各1000ループ)

適用機能

%timeit df ['値'] = df.apply(λ行:行['a']%行['c']、軸= 1)

ループあたり474 µs±5.07 µs(7回の実行の平均±標準偏差、各1000ループ)

0
Gursewak Singh