2

パンダ(v0.8.0)DataFrameで列のスライスを別のスライスで上書きしたい。

以下のコードは、リストされたエラーをスローします。

これを達成するための効率的な代替方法は何でしょうか?

df = DataFrame({'a' : range(0,7),
'b' : np.random.randn(7),
'c' : np.random.randn(7),
'd' : np.random.randn(7),
'e' : np.random.randn(7),
'f' : np.random.randn(7),
'g' : np.random.randn(7)})

# overwrite cols
df.ix[:,'b':'d'] = df.ix[:, 'e':'g']

Traceback (most recent call last):
File "C:\Python27\lib\site-packages\pandas\core\indexing.py", line 68, in __setitem__
self._setitem_with_indexer(indexer, value)
File "C:\Python27\lib\site-packages\pandas\core\indexing.py", line 98, in   _setitem_with_indexer
raise ValueError('Setting mixed-type DataFrames with '
ValueError: Setting mixed-type DataFrames with array/DataFrame pieces not yet supported

編集済み

そして、順列として、設定する行のサブセットを指定するにはどうすればよいですか?

df.ix[df['a'] < 3, 'b':'d'] = df.ix[df['a'] < 3, 'e':'g']
4

1 に答える 1

6

問題は、を使用.ix[]すると、その内容から作成された新しいDataFrameではなく、DataFrameのそのサブセットの実際のメモリオブジェクトへのビューが返されることです。

代わりに使用する

# The left-hand-side does not use .ix, since we're assigning into it.
df[['b','c']] = df.ix[:,'e':'f'].copy()

.copy()スライスを行うために使用する場合は必要になることに注意してください.ix。そうしないと、列「b」と「c」がメモリ内の列「e」と「f」と同じオブジェクトとして設定されます。ここでやりたいこと。

または、コピーの心配を避けるために、次のようにすることができます。

df[['b','c']] = df[['e','f']]

インデックス作成の利便性が重要な場合、この効果をシミュレートする1​​つの方法は、独自の関数を作成することです。

def col_range(df, col1, col2): 
    return list(dfrm.ix[dfrm.index.values[0],col1:col2].index)

これで、次のことができます。

df[col_range(df,'b','d')] = df.ix[:,'e':'g'].copy()

注:の定義でcol_rangeは、データフレームの最初の行を選択する最初のインデックスを使用しました。これを行ったのは、列の範囲を選択するためだけにデータフレーム全体を表示するのは無駄に思えるのに対し、1行はおそらく問題ではないからです。この方法でスライスするとシリーズが生成されるため、列を抽出する方法は実際にインデックスを取得することであり、それらをリストとして返します。

追加の行スライスリクエスト用に追加:

割り当てで行のセットを指定するには、を使用できますが.ix、右側に値のマトリックスのみを指定する必要があります。右側にサブDataFrameの構造があると、問題が発生します。

df.ix[0:4,col_range(df,'b','d')] = df.ix[0:4,'e':'g'].values

たとえば、「a」列が5を超える行のみを取得するように、 [0:4]with[df.index.values[i]:df.index.values[j]]または[df.index.values[i] for i in range(N)]または論理値に置き換えることができます。[df['a']>5]

列'a'を5より大きく、列' e'を10未満にする論理索引付けの例の完全なスライスは、次のようになります。

import numpy as np
my_rows = np.logical_and(df['a'] > 5), df['e'] < 10)
df.ix[my_rows,col_range(df,'b','d')] = df.ix[my_rows,'e':'g'].values

多くの場合、.ix左側を使用する必要はありません(一部の場合にのみ機能し、他の場合には機能しないため、使用しないことをお勧めします)。たとえば、次のようなものです。

df["A"] = np.repeat(False, len(df))
df["A"][df["B"] > 0] = True

.ixそのまま動作します。条件が真である行を識別するために特別な必要はありません。.ix右側のものが複雑な場合、左側に必要なようです。

于 2012-07-15T22:00:05.593 に答える