熊猫在数据框中组合稀疏列

时间:2020-06-07 16:15:19

标签: python pandas dataframe

我正在使用Python和Pandas进行数据分析。我将数据稀疏地分布在如下所示的不同列中

| id | col1a | col1b | col2a | col2b | col3a | col3b |
|----|-------|-------|-------|-------|-------|-------|
|  1 |   11  |   12  |  NaN  |  NaN  |  NaN  |  NaN  |
|  2 |  NaN  |  NaN  |   21  |   86  |  NaN  |  NaN  |
|  3 |   22  |   87  |  NaN  |  NaN  |  NaN  |  NaN  |
|  4 |  NaN  |  NaN  |   NaN |  NaN  |  545  |   32  |

我想将此稀疏分布的数据在不同的列中组合成紧密堆积的列,如下所示。

| id | group |  cola |  colb |
|----|-------|-------|-------|
| 1  |  g1   |   11  |   12  |
| 2  |  g2   |   21  |   86  |
| 3  |  g1   |   22  |   87  |
| 4  |  g3   |  545  |   32  |

我尝试做的是以下操作,但无法正确完成

df['cola']=np.nan
df['colb']=np.nan
df['cola'].fillna(df.col1a,inplace=True)
df['colb'].fillna(df.col1b,inplace=True)
df['cola'].fillna(df.col2a,inplace=True)
df['colb'].fillna(df.col2b,inplace=True)
df['cola'].fillna(df.col3a,inplace=True)
df['colb'].fillna(df.col3b,inplace=True)

但是我认为必须有一种更简洁有效的方法。如何以更好的方式做到这一点?

5 个答案:

答案 0 :(得分:8)

您可以使用df.stack()并假设'id'是您的索引,否则可以将'id'设置为索引。然后使用pd.pivot_table

df = df.stack().reset_index(name='val',level=1)
df['group'] = 'g'+ df['level_1'].str.extract('col(\d+)')
df['level_1'] = df['level_1'].str.replace('col(\d+)','')
df.pivot_table(index=['id','group'],columns='level_1',values='val')

level_1    cola  colb
id group
1  g1      11.0  12.0
2  g2      21.0  86.0
3  g1      22.0  87.0
4  g3     545.0  32.0

答案 1 :(得分:5)

pd.wide_to_long的另一种选择

m = pd.wide_to_long(df,['col'],'id','j',suffix='\d+\w+').reset_index()

(m.join(pd.DataFrame(m.pop('j').agg(list).tolist()))
  .assign(group=lambda x:x[0].radd('g'))
  .set_index(['id','group',1])['col'].unstack().dropna()
  .rename_axis(None,axis=1).add_prefix('col').reset_index())

   id group cola colb
0   1    g1   11   12
1   2    g2   21   86
2   3    g1   22   87
3   4    g3  545   32

答案 2 :(得分:4)

使用:

import re

def fx(s):
    s = s.dropna()
    group = 'g' + re.search(r'\d+', s.index[0])[0]
    return pd.Series([group] + s.tolist(), index=['group', 'cola', 'colb'])

df1 = df.set_index('id').agg(fx, axis=1).reset_index()

# print(df1)

   id   group  cola   colb
0   1    g1    11.0   12.0
1   2    g2    21.0   86.0
2   3    g1    22.0   87.0
3   4    g3    545.0  32.0

答案 3 :(得分:3)

这是一种实现方式:

df = pd.DataFrame({'id':[1,2,3,4],
                   'col1a':[11,np.nan,22,np.nan],
                   'col1b':[12,np.nan,87,np.nan],
                   'col2a':[np.nan,21,np.nan,np.nan],
                   'col2b':[np.nan,86,np.nan,np.nan],
                   'col3a':[np.nan,np.nan,np.nan,545],
                   'col3b':[np.nan,np.nan,np.nan,32]})
df_new = df.copy(deep=False)
df_new['group'] = 'g'+df_new['id'].astype(str)
df_new['cola'] = df_new[[x for x in df_new.columns if x.endswith('a')]].sum(axis=1)
df_new['colb'] = df_new[[x for x in df_new.columns if x.endswith('b')]].sum(axis=1)
df_new = df_new[['id','group','cola','colb']]
print(df_new)

输出:

  id group   cola  colb
0   1    g1   11.0  12.0
1   2    g2   21.0  86.0
2   3    g3   22.0  87.0
3   4    g4  545.0  32.0

因此,如果您有更多后缀(colc,cold,cole,colf等),则可以创建一个循环,然后使用:

suffixes = ['a','b','c','d','e','f']
cols = ['id','group'] + ['col'+x for x in suffixes]
for i in suffixes:
   df_new['col'+i] = df_new[[x for x in df_new.columns if x.endswith(i)]].sum(axis=1)
df_new = df_new[cols]

答案 4 :(得分:2)

感谢@CeliusStingher为数据框提供代码:

一个建议是将id设置为索引,重新排列各列,并从文本中提取数字。创建一个multiIndex,然后堆叠以获得最终结果:

#set id as index
df = df.set_index("id")

#pull out the numbers from each column
#so that you have (cola,1), (colb,1) ...
#add g to the numbers ... (cola, g1),(colb,g1), ...
#create a MultiIndex
#and reassign to the columns
df.columns = pd.MultiIndex.from_tuples([("".join((first,last)), f"g{second}")
                                        for first, second, last
                                        in df.columns.str.split("(\d)")],
                                       names=[None,"group"])

#stack the data 
#to get your result
df.stack()


                 cola   colb
    id  group       
    1   g1      11.0    12.0
    2   g2      21.0    86.0
    3   g1      22.0    87.0
    4   g3      545.0   32.0