【发布时间】:2019-11-03 09:57:44
【问题描述】:
假设我们有一个数据框df,其中包含按时间顺序排列的日期列表。
目标是获取在给定日期具有包含给定日期的日期范围的人数。
df = pd.DataFrame(data={'date': [datetime.date(2007, 12, 1),
datetime.date(2007, 12, 2),
datetime.date(2007, 12, 3)],
'num_people_on_day': [0,0,0]})
dg = pd.DataFrame(data={'person': ['Alice', 'Bob', 'Chuck'],
'start': [datetime.date(2007, 11, 5),
datetime.date(2007, 12, 8),
datetime.date(2007, 1, 5)],
'end': [datetime.date(2007, 12, 6),
datetime.date(2008, 1, 3),
datetime.date(2007, 11, 30)]})
那么对于df中的每个日期,我怎样才能有效地检查所有dg,然后计算返回的数字并将其放入df。
我什至不确定这里是否需要合并(也试图节省内存),并且我真的想尽可能快地编写它。
编辑:好的,所以我想出了一种不同的方法来做到这一点,但我讨厌使用 apply。有没有办法在不使用 .apply 的情况下使用这种新方法?
import pandas as pd
import datetime
df = pd.DataFrame(data={'date': [datetime.date(2007, 12, 1),
datetime.date(2007, 12, 2),
datetime.date(2007, 12, 3)]})
dg = pd.DataFrame(data={'person': ['Alice', 'Bob', 'Chuck', 'Dave'],
'start': [datetime.date(2007, 11, 5),
datetime.date(2007, 12, 8),
datetime.date(2007, 1, 5),
datetime.date(2007, 11, 6)],
'end': [datetime.date(2007, 12, 1),
datetime.date(2008, 1, 3),
datetime.date(2007, 11, 30),
datetime.date(2007, 12, 2)]})
def get_num_persons(date, vec_starts, vec_ends):
"""
Helper function for .apply to get number of persons.
For each given date, if start and end date is
between the given date, then both results are True.
The bitwise AND then only sums these True and True values.
"""
return (((vec_starts <= date) & (vec_ends >= date)).sum())
def num_of_persons(persons, dates_df):
"""
Obtains the number of persons for each day.
"""
dates_df['num_persons'] = dates_df['date'].apply(lambda row:
get_num_persons(row,
persons['start'],
persons['end']))
return dates_df
num_of_persons(dg, df.copy())
【问题讨论】:
-
stackoverflow.com/questions/46525786/… 或 stackoverflow.com/questions/51755268/… 或 stackoverflow.com/questions/44367672/…。然后只需一个 groupby 和 size 即可获得计数。
-
有趣但不是真的。最后两个链接没有用。第一个可能,但我不在这里分类。就像我说的,我什至认为我不需要合并。我会尝试修复我的案例的第一个链接
-
最后两个链接非常有用:
m = df.assign(k=1).merge(dg.assign(k=1))后跟m[m.date.between(m.start, m.end)].groupby('date').size()可以 100% 解决您的问题(可以添加.reindex(df.date).fillna(0),但这不是问题的重点) -
您是正确的,因为它可以工作,但是对我来说,合并会产生太多重复,因此我得到了 MemoryError(appx 50k 行 1200 天 -> 60m 行)。不过,需要研究一种不同的方法。
标签: python python-3.x pandas dataframe vectorization