【问题标题】:Pandas collapse dataframe horizontally熊猫水平折叠数据框
【发布时间】:2021-12-12 01:23:09
【问题描述】:

我有以下布尔值表:

df1 = pd.DataFrame(data={'w': [True, False, False], 
                         'x': [False, True, False],
                         'y': [True, True, True],
                         'z': [True, False, True]},
                         index=pd.Series([1, 2, 3], name='index'))
index w x y z
1 True False True True
2 False True True False
3 False False True True

我创建了一个与df1宽度相同的新表格:

pd.DataFrame(columns=[f'column{num}' for num in range(1, len(df1.columns) + 1)])
column1 column2 column3 column4

我想要做的是折叠来自df1 的列,这样对于每一行,我只显示具有True 值的列:

index column1 column2 column3 column4
1 w y z NA
2 x y NA NA
3 y z NA NA

【问题讨论】:

    标签: python pandas series collapse


    【解决方案1】:

    试试:

    out = np.full(df1.shape, np.nan, dtype='object')
    
    # mask valid columns for each row
    mask = np.arange(df1.shape[1]) < df1.sum(1).values[:,None]
    
    out[mask] = np.where(df1, df1.columns, np.nan)[df1]
    
    out = pd.DataFrame(out)
    

    【讨论】:

      【解决方案2】:

      dotstr.split 的一种方式:

      import numpy as np
      
      df2 = df1.dot(df1.columns+",")
               .str.split(",", expand=True)
               .replace(r'^\s*$', np.nan, regex=True)
               .rename_axis(None)
      df2.columns = [f'column{num}' for num in range(1, len(df2.columns)+1)]
      
      >>> df2
      
          column1 column2 column3 column4
      1         w       y       z     NaN
      2         x       y     NaN     NaN
      3         y       z     NaN     NaN
      

      【讨论】:

      • 不错,我很喜欢 ;) +1
      • 谢谢@mozway - 几乎用过apply,但认为一个可读性较差但更有效的解决方案更好:)
      • 你应该把你的管道包装在(…)中;)
      • 我相信其他人会认识到这是一个不错的答案,恭喜你的 10k 领先一点 ;)
      • .replace(r'^\s*$', np.nan, regex=True)这行的目的是什么?
      【解决方案3】:

      您可以首先使用技巧乘法将列名映射到单元格 (True -> 1, 1*'w' -> 'w' / False -> 0, 0*'w' -> '')

      然后使用自定义键对行进行独立排序(isinstance(w, float) 将在最后推送 NaN/浮点数)

      cols = [f'column{num}' for num in range(1, len(df1.columns) + 1)]
      (df1*df1.columns).where(df1).apply(lambda r: pd.Series(sorted(r, key=lambda x: isinstance(x, float)),
                                                             index=cols), axis=1)
      

      输出:

            column1 column2 column3  column4
      index                                 
      1           w       y       z      NaN
      2           x       y     NaN      NaN
      3           y       z     NaN      NaN
      

      【讨论】:

        【解决方案4】:

        你的情况是 dot 然后 split

        out = df.dot(df.columns+',').str[:-1].str.split(',',expand=True).reindex(columns= np.arange(df.shape[1]))
        Out[34]: 
               0  1     2   3
        index                
        1      w  y     z NaN
        2      x  y  None NaN
        3      y  z  None NaN
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-08-28
          • 2016-09-02
          • 1970-01-01
          • 2019-08-05
          • 1970-01-01
          • 2018-03-11
          • 1970-01-01
          相关资源
          最近更新 更多