在pandas中堆叠数据帧

时间:2018-04-13 08:27:40

标签: python pandas

我正在寻找一种以下列方式在pandas中堆叠数据帧的方法:

id     val
id01   ['a', 'b']
id02   ['b']
id03   []
id04   ['a','c']

为:

id01   'a'
       'b'
id02   'b'
id04   'a'
       'c'

2 个答案:

答案 0 :(得分:1)

如果希望SeriesMultiIndex一起使用stackDataFrame contructor:

s = pd.DataFrame(df['val'].values.tolist(), index=df['id']).stack()
print (s)
id     
id01  0    a
      1    b
id02  0    b
id04  0    a
      1    c
dtype: object

如果需要DataFrame添加双reset_index - 首先删除第二级MultiIndex,第二级为索引创建列:

df = (pd.DataFrame(df['val'].values.tolist(), index=df['id'])
        .stack()
        .reset_index(level=1, drop=True)
        .reset_index(name='val'))
print (df)
     id val
0  id01   a
1  id01   b
2  id02   b
3  id04   a
4  id04   c

如果需要替换重复值,请使用loc + duplicated

df.loc[df['id'].duplicated(), 'id'] = ''
print (df)
     id val
0  id01   a
1         b
2  id02   b
3  id04   a
4         c

答案 1 :(得分:0)

对于一个可以解决的问题,@jezrael's solution很好。

如果要考虑效率问题,建立新数据框通常比stack更有效:

import pandas as pd, numpy as np
from itertools import chain

df = pd.DataFrame({'id': ['id01', 'id02', 'id03', 'id04'],
                   'val': [['a', 'b'], ['b'], [], ['a', 'c']]})

lens = list(map(len, df['val']))

res = pd.DataFrame({'id': np.repeat(df['id'].values, lens),
                    'val': list(chain.from_iterable(df['val']))})

print(res)

#      id val
# 0  id01   a
# 1  id01   b
# 2  id02   b
# 3  id04   a
# 4  id04   c

效果基准

import pandas as pd, numpy as np
from itertools import chain

df = pd.DataFrame({'id': ['id01', 'id02', 'id03', 'id04'],
                   'val': [['a', 'b'], ['b'], [], ['a', 'c']]})

df = pd.concat([df]*100000)

def jp(df):
    lens = list(map(len, df['val']))

    res = pd.DataFrame({'id': np.repeat(df['id'].values, lens),
                        'val': list(chain.from_iterable(df['val']))})

    return res

def jez(df):
    return (pd.DataFrame(df['val'].values.tolist(), index=df['id'])
              .stack()
              .reset_index(level=1, drop=True)
              .reset_index(name='val'))

%timeit jp(df)   # 137 ms per loop
%timeit jez(df)  # 197 ms per loop