Pandas:将具有多个值的新列添加到groupby数据帧

时间:2016-04-23 11:54:49

标签: pandas group-by

对于我的数据框,我想为另一列中的每个唯一值添加一个新列。新列包含几个日期时间条目,其他列的每个唯一值都应该得到。

示例:

Original Df:

ID  
1             
2               
3

新专栏DF:

Date
2015/01/01
2015/02/01
2015/03/01

结果Df:

ID    Date
1     2015/01/01
      2015/02/01
      2015/03/01
2     2015/01/01
      2015/02/01
      2015/03/01
3     2015/01/01
      2015/02/01
      2015/03/01

我试图坚持这个解决方案:https://stackoverflow.com/a/12394122/3856569 但它给了我以下错误:Length of values does not match length of index

任何人都有一个简单的解决方案吗?非常感谢!

2 个答案:

答案 0 :(得分:1)

更新:复制id次6次:

In [172]: %paste
data = """\
id
1
2
3
"""
df = pd.read_csv(io.StringIO(data))
# repeat each ID 6 times
df = pd.DataFrame(df['id'].tolist()*6, columns=['id'])

start_date = pd.to_datetime('2015-01-01')

df['date'] = start_date
df['date'] = df.groupby('id', as_index=False)\
               .transform(lambda x: pd.date_range(start_date,
                                                  freq='1D',
                                                  periods=len(x)))
df.sort_values(by=['id','date'])
## -- End pasted text --
Out[172]:
    id       date
0    1 2015-01-01
3    1 2015-01-02
6    1 2015-01-03
9    1 2015-01-04
12   1 2015-01-05
15   1 2015-01-06
1    2 2015-01-01
4    2 2015-01-02
7    2 2015-01-03
10   2 2015-01-04
13   2 2015-01-05
16   2 2015-01-06
2    3 2015-01-01
5    3 2015-01-02
8    3 2015-01-03
11   3 2015-01-04
14   3 2015-01-05
17   3 2015-01-06

OLD更通用的答案:

准备样本DF:

start_date = pd.to_datetime('2015-01-01')

data = """\
id
1
2
2
3
1
2
3
2
1
"""
df = pd.read_csv(io.StringIO(data))

In [200]: df
Out[200]:
   id
0   1
1   2
2   2
3   3
4   1
5   2
6   3
7   2
8   1

解决方案:

In [201]: %paste
df['date'] = start_date
df['date'] = df.groupby('id', as_index=False)\
               .transform(lambda x: pd.date_range(start_date,
                                                  freq='1D',
                                                  periods=len(x)))
## -- End pasted text --

In [202]: df
Out[202]:
   id       date
0   1 2015-01-01
1   2 2015-01-01
2   2 2015-01-02
3   3 2015-01-01
4   1 2015-01-02
5   2 2015-01-03
6   3 2015-01-02
7   2 2015-01-04
8   1 2015-01-03

排序:

In [203]: df.sort_values(by='id')
Out[203]:
   id       date
0   1 2015-01-01
4   1 2015-01-02
8   1 2015-01-03
1   2 2015-01-01
2   2 2015-01-02
5   2 2015-01-03
7   2 2015-01-04
3   3 2015-01-01
6   3 2015-01-02

答案 1 :(得分:1)

一种相当简单的numpy方法,利用repeattile

import numpy as np
import pandas as pd

N     = 3  # arbitrary number of IDs/dates
ID    = np.arange(N) + 1
dates = pd.date_range('20160101', periods=N)

df = pd.DataFrame({'ID'    : np.repeat(ID, N),
                   'dates' : np.tile(dates, N)})

结果DataFrame:

In [1]: df
Out[1]:
   ID      dates
0   1 2016-01-01
1   1 2016-01-02
2   1 2016-01-03
3   2 2016-01-01
4   2 2016-01-02
5   2 2016-01-03
6   3 2016-01-01
7   3 2016-01-02
8   3 2016-01-03

<强>更新

假设您已经有DataFrameID,正如MaxU指出的那样,您可以平铺ID s

df = pd.DataFrame({'ID'    : np.tile(df['ID'], N),
                   'dates' : np.tile(dates, N)})
# now df needs sorting
df = df.sort_values(by=['ID', 'dates'])

结果DataFrame:

In [5]: df
Out[5]:
   ID      dates
0   1 2016-01-01
3   1 2016-01-01
6   1 2016-01-01
1   2 2016-01-02
4   2 2016-01-02
7   2 2016-01-02
2   3 2016-01-03
5   3 2016-01-03
8   3 2016-01-03