假设有一个狂人日记的 dataframe 如下:

user_name publish_time content
小明 2022-12-30 15:10:00 今天是 2022 年最后一天,我在广东
小刚 2022-01-01 12:23:33 今天是 2022 年第一天,我在加勒比
小王 2022-01-01 12:33:00 今天是 2022 年第一天,我在小刚身边
小刚 2023-01-01 02:15:45 今天是 2023 年第一天,我在百慕大
小明 2023-01-01 00:05:20 今天是 2023 年第一天,我还在广东

现在我们要统计狂人日记里面,同一作者第一次和最后一次发布时间差大于 30 天的行。

乍一看,首先必须统计同一作者至少发布两次的行,也就是上一篇value counts 的内容。

然后再使用 groupby 分组 + filter 过滤实现,这个 filter 相当于 mysql 语句中 groupby 后的 having 语句,是在分组上做筛选的。

所以在上一篇的基础上,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# -*- coding: utf-8 -*-
# author: inspurer(月小水长)
# create_time: 2023/1/7 8:58
# 运行环境 Python3.6+
# github https://github.com/inspurer
# website https://buyixiao.github.io/
# 微信公众号 月小水长

import pandas as pd

input_file = './狂人日记 2022.csv'


def remove_show_count_below_n(input_file, col, n=2):
df = pd.read_csv(input_file)
# 第一步,筛选 user_name 出现大于等于 2 次的行
count_df = pd.DataFrame(df[col].value_counts())
count_df.columns = ['count']
not_below_n_index = count_df[count_df['count'] >= n].index
df = df[df[col].isin(not_below_n_index)]

# 比上一篇新加的內容
df['publish_date'] = pd.to_datetime(df['publish_time']).dt.date
df = df.groupby(col).filter(lambda x: (x['publish_date'].max() - x['publish_date'].min()).days > 30)

df.to_csv('result.csv', index=False, encoding='utf-8-sig')


remove_show_count_below_n(input_file, col='user_name')

仔细想想,第一步真的有必要吗?如果只出现一次,在第二步 publish_date 相减的时候差值为 0,直接就过滤掉了,所以第一步在这个任务是多此一举。简化代码如下:

1
2
3
4
5
6
7
def time_interval_filter(input_file, col, days):
df = pd.read_csv(input_file)
df['publish_date'] = pd.to_datetime(df['publish_time']).dt.date
df = df.groupby(col).filter(lambda x: (x['publish_date'].max() - x['publish_date'].min()).days > days)
df.to_csv('result.csv', index=False, encoding='utf-8-sig')

time_interval_filter(input_file, col='user_name', days=30)