Pandas数据框根据日期划分行

时间:2016-10-23 00:35:02

标签: python pandas numpy

我在每日级别上有一列值,而在每周级别上有另一列值。我想将每日价值除以相应公司和集团当天的每周价值。我试图找出一种没有循环的方法,我觉得有一种方法可以在熊猫或numpy中做到这一点,但我无法弄明白。谢谢你的帮助!

例如,我有两个数据框:

df1 =

Company Group Date       People
A       X     01/07/2015 5
A       X     01/14/2015 10
A       XX    01/07/2015 6
A       XX    01/14/2015 12
B       Y     01/07/2015 4
B       Y     01/14/2015 8
B       YY    01/07/2015 5
B       YY    01/14/2015 4

df2 =

Company Group Date       Value
A       X     01/04/2015 5
A       X     01/06/2015 10
A       X     01/13/2015 15
A       XX    01/05/2015 6
A       XX    01/06/2015 9
A       XX    01/11/2015 9
A       XX    01/14/2015 12
B       Y     01/05/2015 4
B       Y     01/07/2015 6
B       Y     01/13/2015 16
B       Y     01/14/2015 24
B       YY    01/03/2015 10
B       YY    01/11/2015 10
B       YY    01/14/2015 12

我希望结果如下:

Company Group Date       Value/People
A       X     01/04/2015 1
A       X     01/06/2015 2
A       X     01/13/2015 1.5
A       XX    01/05/2015 1
A       XX    01/06/2015 1.5
A       XX    01/11/2015 0.75
A       XX    01/14/2015 1
B       Y     01/05/2015 1
B       Y     01/07/2015 1.5
B       Y     01/13/2015 2
B       Y     01/14/2015 3
B       YY    01/03/2015 2
B       YY    01/11/2015 2.5
B       YY    01/14/2015 3

1 个答案:

答案 0 :(得分:1)

存储在DataFrames和Series中的类似日期的值的基础dtype是NumPy datetime64[ns]datetime64[ns]值的数组可以"裁剪"通过调用astype('datetime64[?]')来规范第二,分钟,小时,日,周,月或年,其中?由相应的单位替换(例如smhDWMY)。

如果我们可以将每个日期分类为规范周,那么我们的问题将在很大程度上得到解决。我们可以使用.astype('datetime64[W]')

执行此操作
In [152]: df1['Week'] = df1['Date'].values.astype('datetime64[W]'); df1
Out[152]: 
  Company       Date Group  People       Week
0       A 2015-01-07     X       5 2015-01-01
1       A 2015-01-14     X      10 2015-01-08
2       A 2015-01-07    XX       6 2015-01-01
3       A 2015-01-14    XX      12 2015-01-08
4       B 2015-01-07     Y       4 2015-01-01
5       B 2015-01-14     Y       8 2015-01-08
6       B 2015-01-07    YY       5 2015-01-01
7       B 2015-01-14    YY       4 2015-01-08

df1df2完成此操作后,我们现在可以合并['Week', 'Group', 'Company']上的DataFrame。这将匹配df1和df2中的相应行。找到价值与人的比例是很容易的。

import pandas as pd
df1 = pd.DataFrame({'Company': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'], 'Date': ['01/07/2015', '01/14/2015', '01/07/2015', '01/14/2015', '01/07/2015', '01/14/2015', '01/07/2015', '01/14/2015'], 'Group': ['X', 'X', 'XX', 'XX', 'Y', 'Y', 'YY', 'YY'], 'People': [5, 10, 6, 12, 4, 8, 5, 4]})

df2 = pd.DataFrame({'Company': ['A', 'A', 'A', 'A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'B', 'B', 'B'], 'Date': ['01/04/2015', '01/06/2015', '01/13/2015', '01/05/2015', '01/06/2015', '01/11/2015', '01/14/2015', '01/05/2015', '01/07/2015', '01/13/2015', '01/14/2015', '01/03/2015', '01/11/2015', '01/14/2015'], 'Group': ['X', 'X', 'X', 'XX', 'XX', 'XX', 'XX', 'Y', 'Y', 'Y', 'Y', 'YY', 'YY', 'YY'], 'Value': [5, 10, 15, 6, 9, 9, 12, 4, 6, 16, 24, 10, 10, 12]})

for df in [df1, df2]:
    df['Date'] = pd.to_datetime(df['Date'])
    df['Week'] = df['Date'].values.astype('datetime64[W]')

result = pd.merge(df2, df1, how='left', on=['Week', 'Group', 'Company'], suffixes=['', '_1'])
result['Value/People'] = result['Value']/result['People']
result = result[['Company', 'Group', 'Date', 'Value/People']]
print(result)

产量

   Company Group       Date  Value/People
0        A     X 2015-01-04          1.00
1        A     X 2015-01-06          2.00
2        A     X 2015-01-13          1.50
3        A    XX 2015-01-05          1.00
4        A    XX 2015-01-06          1.50
5        A    XX 2015-01-11          0.75
6        A    XX 2015-01-14          1.00
7        B     Y 2015-01-05          1.00
8        B     Y 2015-01-07          1.50
9        B     Y 2015-01-13          2.00
10       B     Y 2015-01-14          3.00
11       B    YY 2015-01-03          2.00
12       B    YY 2015-01-11          2.50
13       B    YY 2015-01-14          3.00

请注意,有#34;基本偏移"将种植日期缩短到规范周时需要考虑的问题。换句话说,您需要决定一周何时开始。如果您不喜欢df['Date'].values.astype('datetime64[W]')所做的规范选择,则可能需要在日期中添加偏移量。例如,要将日期添加到df['Date']中的日期,您可以使用:

(df['Date'].values + np.timedelta64(1, 'D')).astype('datetime64[W]')