最初に:これはコードレビューの方が適しているかもしれませんが、ここではより多くのパンダのアフィンユーザーです。あなたが考える場合、それはよくあるそう他の列に応じて新しい列を作成してください:DRYと機能します
、1つは、既存のものから新しい列を計算したいことを自由に動くことを感じる: 次パンダを考えてみましょうDATAFRAME
df = pd.DataFrame({'ItemNumber':np.arange(1, 10),
'A':[1,1,1,2,2,2,3,3,3], 'B': [1,2,3]*3})
print(df)
A B ItemNumber
0 1 1 1
1 1 2 2
2 1 3 3
3 2 1 4
4 2 2 5
5 2 3 6
6 3 1 7
7 3 2 8
8 3 3 9
に我々が計算しましょう
df.loc[(df["A"] == 1) & (df["B"] > 1), 'C'] = 1
df.loc[(df["B"] == 1) & (df["A"] > 1), 'C'] = 2
df.loc[(df["A"] > 1) & (df["B"] > 1), 'C' ] = 3
df.loc[(df["A"] == 1) & (df["B"] == 1), 'C' ] = 4
を経由して新しい列「C」反復的なアプローチと比較すると、これが大きなデータフレームの上にも非常に高速実行するには、hereを発表しました。 特に、そのアプローチのパフォーマンスに関する問題は、上記のコードにつながります。
ただし、このコードはDRYの原則に違反します。コピー貼り付けは気分がいい。上、私たちは私たちの比較を定義し、そこから
def col_equals_value(col, value):
def filter_df(df):
return df[col] == value
return filter_df
def col_greater_value(col, value):
def filter_df(df):
return df[col] > value
return filter_df
:
a1 = col_equals_value('A', 1)
b1 = col_equals_value('B', 1)
agt1 = col_greater_value('A', 1)
bgt1 = col_greater_value('B', 1)
別の機能がに値を割り当てるために必要とされる
それでは、もう少し機能を手放すと2つのカリー化関数を定義列:
def assign_value(cond_1, cond_2, value):
def assign_col_value(df, col):
df.loc[df.apply(cond_1, axis=1) & df.apply(cond_2, axis=1), col] =value
return assign_col_value
最後に、値のマッチンを定義することができます
mapping = [(a1, b1, 4),
(a1, bgt1, 1),
(agt1, b1, 2),
(agt1, bgt1, 3)]
としてグラムはassign_value_functions
m = [assign_value(x, y, z) for (x,y,z) in mapping]
を構築し、データフレームに各機能を適用します。
for f in m:
f(df, 'C')
print(df)
A B ItemNumber
0 1 1 1
1 1 2 2
2 1 3 3
3 2 1 4
4 2 2 5
5 2 3 6
6 3 1 7
7 3 2 8
8 3 3 9
だから、質問は何ですか? このアプローチはあまりスケーラブルではないようです。各比較演算子について、全く新しい関数を定義する必要があるようです。比較演算子を変数にすることはできますか? 現在、私は&演算子で連結された2つの条件のみをサポートしています。それを一般化する方法? 私はapplyメソッドの呼び出しについては不明です。もっと簡単な方法があるはずです。
すべてのヘルプは
ねえ、私は本当にあなたのアイデアが好きです、それはまっすぐだ、マッピングは比較的正確に定義されています。しかし、もっと機能的なソリューションを探しているかどうかはまだ分かりません。私は、任意の多くの条件を可能にするために、演算子モジュールとreduce関数を使用して、私の解を改善できると思います。しかし、マッピング/変換はあまり読みにくいかもしれません。 – Quickbeam2k1