【问题标题】:How can I map the headers to columns in pandas?如何将标题映射到熊猫中的列?
【发布时间】:2017-09-12 22:01:39
【问题描述】:

我有一个像这样的数据框:

A    B    C 
1    0    0
1    1    0
0    1    0
0    0    1

我想要:

 A    B    C  label
 1    0    0   A
 1    1    0   AB
 0    1    0   B
 0    0    1   C

我尝试通过 map 或 apply 来做,但我想不通。

【问题讨论】:

    标签: python pandas


    【解决方案1】:
    df = df.assign(label=[''.join([df.columns[n] for n, bool in enumerate(row) if bool]) 
                          for _, row in df.iterrows()])
    >>> df
       A  B  C label
    0  1  0  0     A
    1  1  1  0    AB
    2  0  1  0     B
    3  0  0  1     C
    

    时间

    # Set-up:
    df_ = pd.concat([df] * 10000)
    
    %%timeit
    # Solution by @Wen 
    df1 = df_.reset_index().melt('index')
    df1 = df1[df1.value==1]
    df['label'] = df1.groupby('index').variable.sum()
    # 10 loops, best of 3: 47.6 ms per loop
    
    %%timeit
    # Solution by @MaxU
    df_['label'] = df_.apply(lambda x: ''.join(df_.columns[x.astype(bool)].tolist()), axis=1)
    # 1 loop, best of 3: 4.99 s per loop
    
    %%timeit
    # Solution by @TedPetrou
    df_['label'] = np.where(df_, df_.columns, '').sum(axis=1)
    # 100 loops, best of 3: 12.5 ms per loop
    
    %%timeit
    # Solution by @Alexander
    df_['label'] = [''.join([df_.columns[n] for n, bool in enumerate(row) if bool]) for _, row in df_.iterrows()]
    # 1 loop, best of 3: 3.75 s per loop
    
    %%time
    # Solution by @PiRSquared
    df_['label'] = df_.dot(df_.columns)
    # CPU times: user 18.1 ms, sys: 706 µs, total: 18.8 ms
    # Wall time: 18.9 ms
    

    【讨论】:

      【解决方案2】:

      这是一个惯用且高效的解决方案

      df['label'] = np.where(df, df.columns, '').sum(axis=1)
      
         A  B  C label
      0  1  0  0     A
      1  1  1  0    AB
      2  0  1  0     B
      3  0  0  1     C
      

      【讨论】:

      • 这很优雅!
      • 不错!!~ :)
      • @TedPetrou 有没有一种 Numpy 方法可以让我得到类似“A+B”或“A/B”而不是“AB”的东西?我可以使用任何 Numpy 方法连接字符串吗?
      【解决方案3】:

      或者使用melt和groupby

      df1 = df.reset_index().melt('index')
      df1 = df1[df1.value==1]
      df['label'] = df1.groupby('index').variable.sum()
      df
      
      Out[976]: 
         A  B  C label
      0  1  0  0     A
      1  1  1  0    AB
      2  0  1  0     B
      3  0  0  1     C
      

      或者

      df['label'] = df.T.apply(lambda x: ''.join(x.index[x==1]),axis=0)
      df
      Out[984]: 
         A  B  C label
      0  1  0  0     A
      1  1  1  0    AB
      2  0  1  0     B
      3  0  0  1     C
      

      【讨论】:

      • 工作但相当慢。如果可能,您通常希望避免使用 groupby
      • @GiantsLoveDeathMetal 今天会开始注意我的代码格式 :)
      • @sunny 你可以为这些答案投票,请接受 Ted 的回答
      • 你们比我善良多了。我必须软化我的灵魂。
      • @TedPetrou 对我来说,声誉远不如学习一个好的解决方案重要!!!!,你的回答让我很开心,我正在努力将我的一些工作代码替换为你的解决方案:),祝你有美好的一天!
      【解决方案4】:

      使用dot

      df.assign(label=df.dot(df.columns))
      
         A  B  C label
      0  1  0  0     A
      1  1  1  0    AB
      2  0  1  0     B
      3  0  0  1     C
      

      使用底层 numpy 数组也是如此

      df.assign(label=df.values.dot(df.columns.values))
      
         A  B  C label
      0  1  0  0     A
      1  1  1  0    AB
      2  0  1  0     B
      3  0  0  1     C
      

      【讨论】:

      • 这个也很聪明!
      • df.dot(df.columns) 很好。
      • 哇,我不知道你可以将整数和对象相乘
      • @TedPetrou 是的!关于df.columns.values 属于dtype object 的敏锐观察。以下失败 df.values.dot(df.columns.values.astype(str)) 和 np.where(df, df.columns, '').astype(str).sum(axis=1)
      【解决方案5】:
      In [101]: df['label'] = df.apply(lambda x: ''.join(df.columns[x.astype(bool)].tolist()), axis=1)
      
      In [102]: df
      Out[102]:
         A  B  C label
      0  1  0  0     A
      1  1  1  0    AB
      2  0  1  0     B
      3  0  0  1     C
      

      PS 我肯定会选择@Ted's solution,因为它更好,而且更快……更快

      【讨论】:

      • @GiantsLoveDeathMetal,我们的 Pandas 社区正在成长——非常感谢! :-)
      • @GiantsLoveDeathMetal 这是 IPython 终端提示符,而不是笔记本。如果数字是 101,这意味着有 100 次不成功的尝试得到正确答案... LOL (j/k ;-))
      • 是的@cᴏʟᴅsᴘᴇᴇᴅ,我很难想到 IPython 终端提示的统称。
      猜你喜欢
      • 1970-01-01
      • 2021-05-03
      • 1970-01-01
      • 2019-09-28
      • 1970-01-01
      • 2021-04-30
      • 2019-05-19
      • 2021-09-03
      • 2021-03-01
      相关资源
      最近更新 更多