【问题标题】:Reverse a get_dummies encoding in pandas反转熊猫中的 get_dummies 编码
【发布时间】:2018-11-09 11:44:42
【问题描述】:

列名是:ID,1,2,3,4,5,6,7,8,9。

col 值为 0 或 1

我的数据框如下所示:

 ID     1    2    3    4    5    6   7   8   9 

1002    0    1    0    1    0    0   0   0   0
1003    0    0    0    0    0    0   0   0   0 
1004    1    1    0    0    0    0   0   0   0
1005    0    0    0    0    1    0   0   0   0
1006    0    0    0    0    0    1   0   0   0
1007    1    0    1    0    0    0   0   0   0
1000    0    0    0    0    0    0   0   0   0
1009    0    0    1    0    0    0   1   0   0

我想要ID前面的列名,其中一行的值为1。

我想要的 Dataframe 应该是这样的:

 ID      Col2
1002       2    // has 1 at Col(2) and Col(4)
1002       4    
1004       1    // has 1 at col(1) and col(2)
1004       2
1005       5    // has 1 at col(5)
1006       6    // has 1 at col(6)
1007       1    // has 1 at col(1) and col(3)
1007       3
1009       3    // has 1 at col(3) and col(7)
1009       7

请帮助我,在此先感谢

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    漂亮的单行:)

    new_df = df.idxmax(axis=1)
    

    【讨论】:

    • 抱歉符号混乱。现在看清楚了吗?
    • 不适用于值为 1 的多个列,@beny 的解决方案无论如何都有效
    • 感谢您的建议。所以,如果我猜对了,get_dummies 生成的df 可以毫无问题地用这个解决方案转换回来,但@beny 的解决方案做得更多。
    【解决方案2】:

    set_index + stack,栈默认dropna

    df.set_index('ID',inplace=True)
    
    df[df==1].stack().reset_index().drop(0,1)
    Out[363]: 
         ID level_1
    0  1002       2
    1  1002       4
    2  1004       1
    3  1004       2
    4  1005       5
    5  1006       6
    6  1007       1
    7  1007       3
    8  1009       3
    9  1009       7
    

    【讨论】:

      【解决方案3】:

      OP 帖子的几个很好的答案。但是,get_dummies 通常用于多个分类特征。 Pandas 使用前缀分隔符prefix_sep 来区分列的不同值。

      以下函数在保持列顺序的同时折叠“虚拟化”数据框:

      def undummify(df, prefix_sep="_"):
          cols2collapse = {
              item.split(prefix_sep)[0]: (prefix_sep in item) for item in df.columns
          }
          series_list = []
          for col, needs_to_collapse in cols2collapse.items():
              if needs_to_collapse:
                  undummified = (
                      df.filter(like=col)
                      .idxmax(axis=1)
                      .apply(lambda x: x.split(prefix_sep, maxsplit=1)[1])
                      .rename(col)
                  )
                  series_list.append(undummified)
              else:
                  series_list.append(df[col])
          undummified_df = pd.concat(series_list, axis=1)
          return undummified_df
      
      

      示例

      >>> df
           a    b    c
      0  A_1  B_1  C_1
      1  A_2  B_2  C_2
      >>> df2 = pd.get_dummies(df)
      >>> df2
         a_A_1  a_A_2  b_B_1  b_B_2  c_C_1  c_C_2
      0      1      0      1      0      1      0
      1      0      1      0      1      0      1
      >>> df3 = undummify(df2)
      >>> df3
           a    b    c
      0  A_1  B_1  C_1
      1  A_2  B_2  C_2
      

      【讨论】:

        【解决方案4】:

        np.argwhere

        v = np.argwhere(df.drop('ID', 1).values).T
        pd.DataFrame({'ID' : df.loc[v[0], 'ID'], 'Col2' : df.columns[1:][v[1]]})
        
          Col2    ID
        0    2  1002
        0    4  1002
        2    1  1004
        2    2  1004
        3    5  1005
        4    6  1006
        5    1  1007
        5    3  1007
        7    3  1009
        7    7  1009
        

        argwhere 获取 DataFrame 中所有非零元素的 i、j 索引。使用第一列索引索引到列ID,使用第二列索引索引到df.columns

        我在第 2 步之前转置 v 以提高缓存效率并减少输入。

        【讨论】:

          【解决方案5】:

          用途:

          df = (df.melt('ID', var_name='Col2')
                 .query('value== 1')
                 .sort_values(['ID', 'Col2'])
                 .drop('value',1))
          

          替代解决方案:

          df = (df.set_index('ID')
                  .mask(lambda x: x == 0)
                  .stack()
                  .reset_index()
                  .drop(0,1))
          

          print (df)
                ID Col2
          8   1002    2
          24  1002    4
          2   1004    1
          10  1004    2
          35  1005    5
          44  1006    6
          5   1007    1
          21  1007    3
          23  1009    3
          55  1009    7
          

          说明

          1. 首先通过meltset_indexunstack 重塑值

          2. 仅过滤1 by query 或将0 转换为NaNs by mask

          3. sort_values 第一个解决方案

          4. 通过reset_indexMultiIndex创建列

          5. 最后删除不必要的列drop

          【讨论】:

          • 有点正确,但相似的ID应该在一起,比如1004有变量1和2,它们应该在一起
          • @MukundS - 使用sort_values 的最后一个版本:)
          猜你喜欢
          • 2018-01-06
          • 2018-09-28
          • 2021-07-27
          • 2017-12-19
          • 2020-07-22
          • 2021-02-02
          • 1970-01-01
          相关资源
          最近更新 更多