【问题标题】:Combine multiple columns into one category column using the column names as value label使用列名作为值标签将多列合并为一个类别列
【发布时间】:2022-09-23 22:36:07
【问题描述】:

我有这个数据

   ID      A      B      C
0   0   True  False  False
1   1  False   True  False
2   2  False  False   True

并想将其转换为

   ID group
0   0     A
1   1     B
2   2     C
  • 我想使用列名作为category 列的值标签。
  • 每行最多只有一个True 值。

这是 MWE

#!/usr/bin/env python3
import pandas as pd

df = pd.DataFrame({
    \'ID\': range(3),
    \'A\': [True, False, False],
    \'B\': [False, True, False],
    \'C\': [False, False, True]
})

result = pd.DataFrame({
    \'ID\': range(3),
    \'group\': [\'A\', \'B\', \'C\']
})
result.group = result.group.astype(\'category\')

print(df)
print(result)

我可以做df.apply(lambda row: ...magic.., axis=1)。但是用 pandas 自己的工具难道没有更优雅的方式吗?

    标签: python pandas


    【解决方案1】:

    您可以使用df.dot

    df['group'] = df[['A', 'B', 'C']].dot(df.columns[1:])
    

    【讨论】:

      【解决方案2】:

      您可以使用pd.melt() 重塑和重命名,然后使用query 对“值”列进行布尔过滤:

      pd.melt(df,id_vars=['ID'],var_name= 'group').query('value') 
      
         ID group  value
      0   0     A   True
      4   1     B   True
      8   2     C   True
      

      链接.drop('value',axis=1).reset_index(drop=True) 将给出您的最终输出:

         ID group
      0   0     A
      1   1     B
      2   2     C
      

      【讨论】:

        【解决方案3】:

        还有一种方式:

        df.set_index(['ID'])\
          .rename_axis('group', axis=1)\ # getting column name correct
          .stack()\                      # reshaping getting column headers into dataframe rows
          .loc[lambda x: x]\             # filtering for True
          .reset_index()\                # moving ID back into dataframe columns
          .drop(0, axis=1)               # dropping boolean column
        

        输出:

           ID group
        0   0     A
        1   1     B
        2   2     C
        

        【讨论】:

          【解决方案4】:

          您可以使用 melt 然后根据值正确的列进行查找以获得您期望的结果

          df = df.melt(id_vars = 'ID', var_name = 'group')
          df.loc[df['value'] == True][['ID', 'group']]
          

          【讨论】:

            【解决方案5】:

            melt 更详细,但这会在重塑期间删除无效列:

            (df.set_index('ID')
               .rename_axis(columns='group')
               .replace(False, pd.NA)
               .stack().reset_index().drop(columns=0)
            )
            

            输出:

               ID group
            0   0     A
            1   1     B
            2   2     C
            

            【讨论】:

              【解决方案6】:

              idxmax

              s = df.set_index('ID')
              s.idxmax(1).where(s.any(1))
              

              ID
              0    A
              1    B
              2    C
              dtype: object
              

              【讨论】:

                【解决方案7】:

                试试applylambda

                df.set_index('ID').apply(lambda x : x.index[x][0],axis=1)
                Out[39]: 
                ID
                0    A
                1    B
                2    C
                dtype: object
                

                【讨论】:

                  【解决方案8】:

                  df['group'] = df[['A', 'B', 'C']].dot(df.columns[1:])

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2020-01-14
                    • 2022-08-02
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2020-05-01
                    相关资源
                    最近更新 更多