Python関数を1つのパンダ列に適用し、出力を複数の列に適用します
こんにちはコミュニティ、
私はたくさんの答えやブログを読んだのですが、私が見逃している簡単なことを理解することができません!。'conditions'関数を使用してすべての条件を定義し、それを1つのデータフレーム列に適用しています。また、条件が満たされる場合は、2つの新しいデータフレーム列「cat」と「subcat」を作成/更新する必要があります。
あなたたちがここで私を助けることができればそれは大きな助けになるでしょう!
dict = {'remark':['NA','NA','Category1','Category2','Category3'],
'desc':['Present','Present','NA','Present','NA']
}
df = pd.DataFrame(dict)
データフレームは次のようになります。
remark desc
0 NA Present
1 NA Present
2 Category1 NA
3 Category2 Present
4 Category3 NA
以下のように条件を定義する関数を作成しました。
def conditions(s):
if (s == 'Category1'):
x = 'insufficient'
y = 'resolution'
elif (s=='Category2):
x= 'insufficient'
y= 'information'
elif (s=='Category3):
x= 'Duplicate'
y= 'ID repeated'
else:
x= 'NA'
y= 'NA'
return (x,y)
データフレーム列で上記の関数を実行するためのアイデアは複数ありますが、うまくいきません。
df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([conditions(df)[0],conditions(df)[1]]))
予想されるデータフレームは次のようになります。
remark desc cat subcat
0 NA Present NA NA
1 NA Present NA NA
2 Category1 NA insufficient resolution
3 Category2 Present insufficient information
4 Category3 NA Duplicate ID repeated
どうもありがとう。
回答
これを回避する1つの方法は、リスト内包表記を使用することです。
df[['cat', 'subcat']] = [("insufficient", "resolution") if word == "Category1" else
("insufficient", "information") if word == "Category2" else
("Duplicate", "ID repeated") if word == "Category3" else
("NA", "NA")
for word in df.remark]
remark desc cat subcat
0 NA Present NA NA
1 NA Present NA NA
2 Category1 NA insufficient resolution
3 Category2 Present insufficient information
4 Category3 NA Duplicate ID repeated
@ dm2の答えは、関数でそれを実行する方法を示しています。最初のapply(conditions)
タプルを含むシリーズを作成し、第二は、apply
あなたが、その後に割り当てることができるデータフレーム形成、個々の列を作成cat
し、をsubcat
。
私がリスト内包表記を提案する理由は、あなたが文字列を扱っているものであり、パンダでは、バニラPythonを介して文字列を扱う方が速い場合が多いからです。また、リスト内包表記を使用すると、処理が1回実行されるため、条件関数を適用してからを呼び出す必要はありませんpd.Series
。それはあなたに速い速度を与えます。テストはこれを主張またはデバンキングします。
あなたができること:
df[['cat','subcat']] = df['remark'].apply(conditions).apply(pd.Series)
出力:
remark desc cat subcat
0 NA Present NA NA
1 NA Present NA NA
2 Category1 NA insufficient resolution
3 Category2 Present insufficient information
4 Category3 NA Duplicate ID repeated
編集:これは、既存の関数を適用するためのより簡単な方法かもしれませんが、巨大なDataFrameがある場合は、コードを高速化するために、リスト内包表記を使用して@sammywemmyによる回答を確認してください。
dataframe
ラムダ変数(x
)を渡す必要がある場所全体を渡します。
df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([*conditions(x)]))
*
iterablesではunpack
それらを実行できるため、出力を抽出するために同じ関数を2回呼び出す必要はありません。おそらくコンパイラはこれを解決しますが、私はそうは思いません...
series.replace
マッピング辞書で使用できます
df['cat'] = df.remark.replace({'Category1': 'insufficient',
'Category2': 'insufficient', 'Category3': 'Duplicate'})
df['subcat'] = df.remark.replace({'Category1': 'resolution',
'Category2': 'information', 'Category3': 'ID repeated'})
print(df)
remark desc cat subcat
0 NA Present NA NA
1 NA Present NA NA
2 Category1 NA insufficient resolution
3 Category2 Present insufficient information
4 Category3 NA Duplicate ID repeated