使用group by转换数据框并包含额外的列值

时间:2018-01-24 19:52:46

标签: python pandas

鉴于此数据框:

import numpy as np
import pandas as pd

df = pd.DataFrame([['a1' , '1'], ['a2' , '2'], ['stop' , '3'], ['a2' , '4'], ['a4' , '5'], ['a5' , '6'], ['stop' , '7'], ['a6' , '8']],
                      columns=['a' , 'b'])
mask = df['a'].eq('stop')
print(df)
      a  b
0  a1    1
1  a2    2
2  stop  3
3  a2    4
4  a4    5
5  a5    6
6  stop  7
7  a6    8

处理将数据框转换为:

stop = mask[::-1].idxmax()
mask = mask[:stop]
c = df['a'][:stop].copy()
c.groupby(mask.cumsum()).apply(lambda s: s[s!='stop'].tolist())
a
0    [a1, a2]    
1    [a2, a4, a5]
Name: a, dtype: object

何时停止'遇到会创建一个包含先前值的新数组。

我试图创建一个元组列表,其中列b从上面的数据帧df映射到列a的id。这是创建时的预期数据框结构:

0    [(a1 , 1), (a2 , 2)]    
1    [(a2 , 3), (a4 , 4), (a5 , 5)]

到目前为止,这是我的尝试:

def get_value(x) : 
    to_ret = []
    for a in x : 
        to_ret.append( (a , df[df['a'] == a]['b']))
    return to_ret


c1 = c.groupby(mask.cumsum()).apply(lambda s: s[s!='stop'].tolist())
c1.map(lambda x : get_value(x))

呈现:

a
0    [(a1, [1]), (a2, [2, 4])]           
1    [(a2, [2, 4]), (a4, [5]), (a5, [6])]
Name: a, dtype: object

这似乎是一个简单问题的复杂部分解决方案。是否有另一种转换此数据帧的方法?

2 个答案:

答案 0 :(得分:3)

您好像可以将数据框转换为2元组系列,将 转换为类似的内容(groupby + apply + tolist) -

df.apply(tuple, 1)[:stop]\
  .groupby(mask.cumsum())\
  .apply(lambda s: s[s.str[0] !='stop'].tolist())

a
0             [(a1, 1), (a2, 2)]
1    [(a2, 4), (a4, 5), (a5, 6)]

答案 1 :(得分:3)

另一个appraoch

df['stop_loc'] = (df['a'] == 'stop').cumsum()
df_new = df[(df['a'] != 'stop') & (df['stop_loc'] != df['stop_loc'].max())].groupby('stop_loc').apply(lambda x: list(zip(x.a, x.b)))

0             [(a1, 1), (a2, 2)]
1    [(a2, 4), (a4, 5), (a5, 6)]