Python関数を1つのパンダ列に適用し、出力を複数の列に適用します

Aug 20 2020

こんにちはコミュニティ、

私はたくさんの答えやブログを読んだのですが、私が見逃している簡単なことを理解することができません!。'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

どうもありがとう。

回答

2 sammywemmy Aug 20 2020 at 04:10

これを回避する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。それはあなたに速い速度を与えます。テストはこれを主張またはデバンキングします。

2 dm2 Aug 20 2020 at 04:12

あなたができること:

 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による回答を確認してください。

1 Quentin Aug 20 2020 at 04:13

dataframeラムダ変数(x)を渡す必要がある場所全体を渡します。

df[['cat','subcat']] = df['remark'].apply(lambda x: pd.Series([*conditions(x)]))

*iterablesではunpackそれらを実行できるため、出力を抽出するために同じ関数を2回呼び出す必要はありません。おそらくコンパイラはこれを解決しますが、私はそうは思いません...

RichieV Aug 20 2020 at 04:11

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