如何基于过滤后的总和合并两个DataFrame?

时间:2018-08-23 14:58:55

标签: python pandas dataframe

我有两个看起来像这样的数据框

   start_date    end_date
1  2018-01-01  2018-01-31
2  2018-01-15  2018-02-28
3  2018-01-31  2018-03-15
4  2018-01-07  2018-04-30

            value
2018-01-01      1
2018-01-02      4
2018-01-03      2
2018-01-04     10
2018-01-05      0
...           ...
2018-12-28      1
2018-12-29      7
2018-12-30      9
2018-12-31      5

我正在尝试向第一个DataFrame添加一个新列,其中包含第二个DataFrame的求和值,并按start_dateend_date进行过滤。像

   start_date    end_date  total_value
1  2018-01-01  2018-01-31           47  # Where 47 is the sum of values between 2018-01-01 and 2018-01-31, inclusive
2  2018-01-15  2018-02-28           82
3  2018-01-31  2018-03-15          116
4  2018-01-07  2018-04-30          253

我想我可以用apply来做到这一点(基本上只是用start_dateend_date过滤并求和第二个DataFrame并返回总和),但是我想知道是否有一个而是使用简洁的熊猫式解决方案。

3 个答案:

答案 0 :(得分:4)

新答案

我正在使用OP数据,需要对其进行轻微按摩

df2 = df2.asfreq('D').fillna(0, downcast='infer')

然后我们要进行cumsum的操作,但要增加班次。

s = df2.value.cumsum()
starts = df1.start_date.map(s.shift().fillna(0, downcast='infer'))
ends = df1.end_date.map(s)

df1.assign(total_value=ends - starts)

  start_date   end_date  total_value
1 2018-01-01 2018-01-31           17
2 2018-01-15 2018-02-28            0
3 2018-01-31 2018-03-15            0
4 2018-01-07 2018-04-30            0

旧答案

很酷,但是不准确。这是开始日期之后的数字总和。为了包括开始日期,我必须使用班次。见上文。

您可以使用cumsum并有所作为。

df1.assign(
    total_value=df1.applymap(df2.cumsum().value.get).eval('end_date - start_date'))

  start_date   end_date  total_value
1 2018-01-01 2018-01-31          145
2 2018-01-15 2018-02-28          229
3 2018-01-31 2018-03-15          212
4 2018-01-07 2018-04-30          535

设置

np.random.seed([3, 1415])

min_date = df1.values.min()
max_date = df1.values.max()
tidx = pd.date_range(min_date, max_date)
df2 = pd.DataFrame(dict(value=np.random.randint(10, size=len(tidx))), tidx)

答案 1 :(得分:3)

设置

location.pathname

使用循环和df2.reset_index(inplace=True) 创建条件(zipoutput的索引相匹配很重要)

df1

使用conditions = [df2['index'].between(i, j) for i, j in zip(df1.start_date, df1.end_date)] output = df1.index ,然后使用np.select

groupby

最后合并:

tmp = df2.assign(flag=np.select(conditions, output, np.nan))
tmp = tmp.dropna().groupby('flag').value.sum()

输出:

df1.merge(tmp.to_frame(), left_index=True, right_index=True)

答案 2 :(得分:2)

请注意,这将是O(m * n)方法,为合并创建新的密钥

df1['Newkey']=1    
df2['Newkey']=1    
df2.reset_index(inplace=True)    
mergefilterdf=df1.merge(df2).\
                loc[lambda  x : (x['start_date']<=x['index'])&(x['end_date']>=x['index'])]
mergefilterdf.groupby(['start_date','end_date']).value.sum()
Out[331]: 
start_date  end_date  
2018-01-01  2018-01-31    17
Name: value, dtype: int64