【问题标题】:Melt group of columns into target columns by name按名称将列组融合为目标列
【发布时间】:2018-10-10 17:28:28
【问题描述】:

这个问题建立在Pandas melt several groups of columns into multiple target columns by name 之上。但是,我的数据以一种令人讨厌的方式组织

import pandas as pd

df = pd.DataFrame([(101, 'a', 'b', 'c', 'd', 'e', 'f', 1, 2, 3, 4, 5, 6, 'aa', 'bb', 'cc', 'dd', 'ee', 'ff'),
                   (102,'g', 'h', 'i', 'j', 'k', 'l' , 7, 8, 9, 10, 11, 12, 'gg', 'hh', 'ii', 'jj', 'kk', 'll')], 
                   columns=['id','a__1', 'a__2', 'a__3', 'a_1', 'a_2', 'a_3','b__1', 'b__2', 'b__3', 'b_1', 'b_2', 'b_3','c__1', 'c__2', 'c__3', 'c_1', 'c_2', 'c_3'])

df

数据框如下所示:

    id a__1 a__2 a__3 a_1 a_2 a_3  b__1  b__2  b__3  b_1  b_2  b_3 c__1 c__2  \
0  101    a    b    c   d   e   f     1     2     3    4    5    6   aa   bb   
1  102    g    h    i   j   k   l     7     8     9   10   11   12   gg   hh   

  c__3 c_1 c_2 c_3  
0   cc  dd  ee  ff  
1   ii  jj  kk  ll 

正如您所见,并非所有分隔符都只有一个下划线,它们有时是两个下划线。

最后我想按以下方式组织我的数据,注意 a__1 应该在 a_1 之前,依此类推:

     id   a   b   c
0   101   a   1   aa
1   101   b   2   bb
2   101   c   3   cc
3   101   d   4   dd
4   101   e   5   ee
5   101   f   6   ff   
6   102   g   7   gg
7   102   h   8   hh
8   102   i   9   ii
9   102   j   10  jj
10  102   k   11  kk
11  102   l   12  ll

基本上我的问题是,有时我不是只有一个下划线,而是 2。现在这不适用于 pd.wide_to_long 函数,因为我无法将分隔符参数设置为“_”或“__”。希望你能理解我的问题。

【问题讨论】:

  • __ 简单替换为_ 然后按照您提到的工作进行吗?

标签: python pandas dataframe transform


【解决方案1】:

您可以使用 repalce 将所有 '_' 和 '__' 复制到 '',然后我们使用 stack 重塑您的 df,使用 cumcount 创建唯一密钥后我们可以实现您所需要的

df.columns=df.columns.str.replace('_','')
s=df.set_index('id').stack().reset_index(level=1)
s.level_1=s.level_1.str[0]
s['New']=s.groupby('level_1').cumcount()



s.set_index(['New','level_1'],append=True)[0].unstack()


Out[509]: 
level_1  a   b   c
id  New           
101 0    a   1  aa
    1    b   2  bb
    2    c   3  cc
    3    d   4  dd
    4    e   5  ee
    5    f   6  ff
102 6    g   7  gg
    7    h   8  hh
    8    i   9  ii
    9    j  10  jj
    10   k  11  kk
    11   l  12  ll

【讨论】:

    【解决方案2】:

    你可以使用@Wen 老最爱pd.wide_to_long

    pd.wide_to_long(df,['a','b','c'],i='id',j='new',sep='_',suffix='.')\
      .reset_index('new', drop=True)\
      .sort_index()
    

    输出:

         a   b   c
    id            
    101  a   1  aa
    101  b   2  bb
    101  c   3  cc
    101  d   4  dd
    101  e   5  ee
    101  f   6  ff
    102  g   7  gg
    102  h   8  hh
    102  i   9  ii
    102  j  10  jj
    102  k  11  kk
    102  l  12  ll
    

    【讨论】:

    • 我能问一下这个 pd.wide_to_long 和我链接的问题有什么区别吗?
    • 没有区别,只是不明白为什么要使用pd.wide_to_long。无论如何都不会使用“New”列或“dropme”列,因此单个 _ vs __ 是一个问题。只需使用一个 _ 作为分隔符就可以了。
    • 还有一个问题,如果我还有一个名为 b 的列,例如,它的值介于 b__3 和 b_1 之间,比如 3.5。由于现在列名之一与存根相同,我将如何更改您的方法?
    • @EliasK。那时,我将重命名列以标准化,然后使用通用分隔符。 IE。 df.coumns = df.columns.str.replace('.','_') 或类似的分隔符。
    猜你喜欢
    • 2016-12-16
    • 2016-05-13
    • 2013-09-03
    • 2019-08-18
    • 1970-01-01
    • 2014-06-23
    • 1970-01-01
    相关资源
    最近更新 更多