我有一个带有日期时间对象列的一个月DataFrame和一堆我想应用的功能-按周。因此,我想遍历DataFrame并将功能应用于每个星期。如何在每周的时间段内迭代?
这是一些随机的日期时间代码:
np.random.seed(123)
n = 500
df = pd.DataFrame(
{'date':pd.to_datetime(
pd.DataFrame( { 'year': np.random.choice(range(2017,2019), size=n),
'month': np.random.choice(range(1,2), size=n),
'day': np.random.choice(range(1,28), size=n)
} )
) }
)
df['random_num'] = np.random.choice(range(0,1000), size=n)
我的每周时长不一致(有时我每周有1000条推文,有时是100,000条)。能否有人给我一个例子,说明如何按周遍历此数据框? (我不需要聚合或groupby函数。)
答案 0 :(得分:1)
如果您真的不想使用groupby和聚合,则:
for week in df['date'].dt.week.unique():
this_weeks_data = df[df['date'].dt.week == week]
如果您拥有一年以上的数据,这当然会出错。
答案 1 :(得分:0)
给出示例数据框
date random_num
0 2017-01-01 214
1 2018-01-19 655
2 2017-01-24 663
3 2017-01-26 723
4 2017-01-01 974
首先,您可以尝试将索引设置为datetime对象,如下所示
df.set_index(df.date, inplace=True)
df.drop('date', axis=1, inplace=True)
这会将索引设置为日期列,并删除原始列。你会得到
>>> df.head()
date random_num
2017-01-01 214
2018-01-19 655
2017-01-24 663
2017-01-26 723
2017-01-01 974
然后,您可以使用熊猫groupby
函数根据您的频率对数据进行分组,并应用您选择的任何函数。
# To group by week and count the number of occurances
>>> df.groupby(pd.Grouper(freq='W')).count().head()
date random_num
2017-01-01 11
2017-01-08 65
2017-01-15 55
2017-01-22 66
2017-01-29 45
# To group by week and sum the random numbers per week
>>> df.groupby(pd.Grouper(freq='W')).sum().head()
date random_num
2017-01-01 7132
2017-01-08 33916
2017-01-15 31028
2017-01-22 31509
2017-01-29 22129
您还可以使用熊猫的myFunction
方法来应用任何通用函数apply
df.groupby(pd.Grouper(freq='W')).apply(myFunction)
如果要在分组后将函数myFunction
应用于任何特定的列columnName
,也可以按照以下步骤进行操作
df.groupby(pd.Grouper(freq='W'))[columnName].apply(myFunction)
答案 2 :(得分:0)
[已解决多年]
pd.Grouper(freq='W')
可以正常工作,但有时我会遇到一些与周数不均时如何拆分周数有关的不良行为。因此,这就是为什么我有时喜欢像本示例中所示手动进行周拆分。
因此,拥有跨越多年的数据集
import numpy as np
import pandas as pd
import datetime
# Create dataset
np.random.seed(123)
n = 100000
date = pd.to_datetime({
'year': np.random.choice(range(2017, 2020), size=n),
'month': np.random.choice(range(1, 13), size=n),
'day': np.random.choice(range(1, 28), size=n)
})
random_num = np.random.choice(
range(0, 1000),
size=n)
df = pd.DataFrame({'date': date, 'random_num': random_num})
例如:
print(df.head())
date random_num
0 2019-12-11 413
1 2018-06-08 594
2 2019-08-06 983
3 2019-10-11 73
4 2017-09-19 32
首先创建一个帮助程序索引,该索引使您可以按周(还考虑年份)进行迭代:
df['grp_idx'] = df['date'].apply(
lambda x: '%s-%s' % (x.year, '{:02d}'.format(x.week)))
print(df.head())
date random_num grp_idx
0 2019-12-11 413 2019-50
1 2018-06-08 594 2018-23
2 2019-08-06 983 2019-32
3 2019-10-11 73 2019-41
4 2017-09-19 32 2017-38
然后只应用对每周子集进行计算的函数,就像这样:
def something_to_do_by_week(week_data):
"""
Computes the mean random value.
"""
return week_data['random_num'].mean()
weekly_mean = df.groupby('grp_idx').apply(something_to_do_by_week)
print(weekly_mean.head())
grp_idx
2017-01 515.875668
2017-02 487.226704
2017-03 503.371681
2017-04 497.717647
2017-05 475.323420
一旦有了每周指标,您可能希望返回实际日期,该日期比年周指数更有用:
def from_year_week_to_date(year_week):
"""
"""
year, week = year_week.split('-')
year, week = int(year), int(week)
date = pd.to_datetime('%s-01-01' % year)
date += datetime.timedelta(days=week * 7)
return date
weekly_mean.index = [from_year_week_to_date(x) for x in weekly_mean.index]
print(weekly_mean.head())
2017-01-08 515.875668
2017-01-15 487.226704
2017-01-22 503.371681
2017-01-29 497.717647
2017-02-05 475.323420
dtype: float64
就像进行健全性检查一样,使用pd.Grouper(freq='W')
进行的计算给了我几乎相同的结果(不知何故,它在pd.Series的开头增加了一周的时间)
df.set_index('date').groupby(
pd.Grouper(freq='W')
).mean().head()
Out[27]:
random_num
date
2017-01-01 532.736364
2017-01-08 515.875668
2017-01-15 487.226704
2017-01-22 503.371681
2017-01-29 497.717647