2

文字列を含むデータの列があり、対応するデータ文字列から最初の 2 文字のみを取得する新しい列を作成したいと考えています。

これに関数を使用するのは理にかなっているように見えますapplyが、期待どおりには機能しません。の他の用途と一貫性があるようにも見えませんapply。下記参照。

In [205]: dfrm_test = pandas.DataFrame({"A":np.repeat("the", 10)})

In [206]: dfrm_test
Out[206]:
     A
0  the
1  the
2  the
3  the
4  the
5  the
6  the
7  the
8  the
9  the

In [207]: dfrm_test["A"].apply(lambda x: x+" cat")
Out[207]:
0    the cat
1    the cat
2    the cat
3    the cat
4    the cat
5    the cat
6    the cat
7    the cat
8    the cat
9    the cat
Name: A

In [208]: dfrm_test["A"].apply(lambda x: x[0:2])
Out[208]:
0    the
1    the
Name: A

これに基づいて、apply内部で呼び出されたものと同等の NumPy を実行するだけのようです。つまり、最初の例applyと同じことを実行しているように見えます。arr + " cat"そして、NumPy がたまたまそれをブロードキャストした場合、それは機能します。そうでない場合は、そうではありません。

applyしかし、これはドキュメントの約束から外れているようです。以下は、pandas.Series.apply が期待する必要がある内容の引用です。

Series の値に対して関数を呼び出します。単一の値のみを期待する ufunc または Python 関数にすることができます (リンク)

単一の値のみを期待する Python 関数を受け入れることができると明示的に述べています。そして、機能していない機能 ( lambda x: x[0:2]) は、間違いなくそれを満たしています。単一の引数が配列でなければならないとは言っていません。また、 のようなものnumpy.sqrtが単一の入力に一般的に使用されていることを考えると (したがって、配列だけでなく)、Pandas がそのような関数で動作することを期待するのは当然のようです。

applyここに欠けている使用方法はありますか?

注:以下に独自の追加機能を作成しました:

def ix2(arr):
    return np.asarray([x[0:2] for x in arr])

このバージョンPandas で動作することを確認しましapplyた。しかし、これは論外です。Series オブジェクトの上で外部的に動作するものを記述する方が、リスト内包表記を使用して Series のコンテンツを効果的にループするラッパーを常に記述しなければならないよりも簡単です。applyこれは特に、ユーザーから離れて抽象化することになっているものではありませんか?

Pandas バージョン 0.7.3 を使用していますが、これは職場の共有ネットワーク上にあるため、最新のリリースにアップグレードする方法がありません。

追加した:

この動作はバージョン 0.7.3 からバージョン 0.8.1 に変更されることを確認できました。0.8.1 では、NumPy ufunc ラッパーなしで期待どおりに動作します。

私の推測では、コード内で誰かが使用しようとしていたnumpy.vectorizenumpy.frompyfunc、try-except ステートメント内で使用されていたようです。おそらく、私が使用している特定のラムダ関数では正しく動作しなかったためexcept、コードの一部では、デフォルトで一般的な NumPy ブロードキャストに依存するようになりました。

可能であれば、Pandas 開発者からこれに関する確認を得ることができれば幸いです。しかし当面は、ufunc の回避策で十分です。

4

3 に答える 3

3

私が考えることができる1つの回避策は、Python関数を次のように変換することnumpy.ufuncですnumpy.frompyfunc

numpy.frompyfunc((lambda x: x[0:2]), 1, 1)

でこれを使用しますapply

In [50]: dfrm_test
Out[50]:
     A
0  the
1  the
2  the
3  the
4  the
5  the
6  the
7  the
8  the
9  the

In [51]: dfrm_test["A"].apply(np.frompyfunc((lambda x: x[0:2]), 1, 1))
Out[51]:
0    th
1    th
2    th
3    th
4    th
5    th
6    th
7    th
8    th
9    th
Name: A

In [52]: pandas.version.version
Out[52]: '0.7.3'

In [53]: dfrm_test["A"].apply(lambda x: x[0:2])
Out[53]:
0    the
1    the
Name: A
于 2012-09-12T18:09:32.177 に答える
1

試すdfrm_test.A.map(lambda x: x[0:2])

于 2012-09-12T22:25:19.500 に答える
1

これは pandas 0.8.1 以降で機能します。

In [47]: dfrm_test.A.str[:2]
Out[47]: 
0    th
1    th
2    th
3    th
4    th
5    th
6    th
7    th
8    th
9    th
Name: A
于 2012-10-24T16:19:17.057 に答える