python - 计算一个日期在另一个日期的 x 个月内出现的次数

标签 python pandas

使用以下数据框:

import pandas as pd

df = pd.DataFrame(
{
    'user_id': ['1', '2', '3'],
    'promo_date': ['01012023','01012023','01012023'],
    'logins': [['10242022', '11242022', '04122023'], ['10242022', '04122023'], []]
 }

)

看起来像:

  user_id promo_date                          logins
0       1   01012023  [10242022, 11242022, 04122023]
1       2   01012023            [10242022, 04122023]
2       3   01012023                              []

我正在尝试统计促销日期前 3 个月内某人登录的所有次数。我有一个使用 apply 调用的函数来执行此操作,但对于我拥有的记录数量来说,它太慢了。

from dateutil.relativedelta import relativedelta
EXPECTED_DATE_FORMAT = '%m%d%Y'


def calculate_NTimesLoggedInXMonths(x_months, promo_date_str, login_dates):
    login_count = 0
    promo_date = pd.to_datetime(promo_date_str, format=EXPECTED_DATE_FORMAT)
    x_month_back = promo_date - relativedelta(months=x_months)
    for date in login_dates:
        if x_month_back < pd.to_datetime(date, format=EXPECTED_DATE_FORMAT) < promo_date:
            login_count += 1
    return login_count

# Start the calculation
start = datetime.now()
print("Start time is ", start)
df[f'NTimesLoggedIn3Months'] = df.apply(
    lambda row: calculate_NTimesLoggedInXMonths(3, row['promo_date'], row['logins']),
    axis=1
)

end = datetime.now()
print("Run time:", end - start)

预期结果是:

  promo_date                          logins  NTimesLoggedIn3Months
0   01012023  [10242022, 11242022, 04122023]                      2
1   01012023            [10242022, 04122023]                      1
2   01012023                              []                      0    

我认为最好的解决方案是利用 Series.dt 访问器,但我不确定如何使用列表来做到这一点。即使我将列表分开,以便每次登录时都会重复每个 id,我仍然不确定如何使用 dt 访问器来获取此计数。

最佳答案

我建议扩展列表,以便更好地利用 pandas 优化来处理 Series。

exp = df.explode('logins')
exp['promo_date'] = pd.to_datetime(exp['promo_date'], format='%m%d%Y')
exp['logins'] = pd.to_datetime(exp['logins'], format='%m%d%Y')

exp['within_3mo'] = ((exp['promo_date'] - pd.DateOffset(months=3) <= exp['logins']) & 
    (exp['logins'] <= exp['promo_date']))

然后,您可以使用 user_id 上的 groupby 来计算总和。

>>> exp.groupby('user_id')['within_3mo'].sum()
user_id
1    2
2    1
3    0
Name: within_3mo, dtype: int64

关于python - 计算一个日期在另一个日期的 x 个月内出现的次数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74748653/

相关文章:

python - python 中的负零

python - 使用 pycharm 在 vagrant 实例中使用 python3 作为 docker 容器调试 django 应用程序

coding-style - 在 Python 中创建常量的约定

python - 如何将 ldap3 条目处理为 json 或列表以进行进一步的数据处理?

python - 在 pandas 中,如何绘制多个索引?

c# - 通过 C++ 桥从 .NET 调用 Python

python - Pandas :无法将日期时间 YYYY-mm-dd 转换为 dd-mm-YYYY

python - 根据字符串在每个循环中调用不同的变量

python - 如何迭代行并根据同一行中其他字段的内容查询特定字段?

python - 尽管我所有的行值都是数字(不是 NaN),为什么 pandas 2min 存储桶打印 NaN?