[英]Python - pandas - find most frequent combination with tie-resolution - performance
数据
我有一个看起来像这样的数据集:
| id | string_col_A | string_col_B | creation_date |
|-------|--------------|--------------|---------------|
| x12ga | STR_X1 | STR_Y1 | 2020-11-01 |
| x12ga | STR_X1 | STR_Y1 | 2020-10-10 |
| x12ga | STR_X2 | STR_Y2 | 2020-11-06 |
| x21ab | STR_X4 | STR_Y4 | 2020-11-06 |
| x21ab | STR_X5 | STR_Y5 | 2020-11-02 |
| x11aa | STR_X3 | STR_Y3 | None |
目标
即上表的结果是:
| id | string_col_A | string_col_B |
|-------|--------------|--------------|
| x12ga | STR_X1 | STR_Y1 |
| x21ab | STR_X4 | STR_Y4 |
| x11aa | STR_X3 | STR_Y3 |
解释
x12ga
,解释很简单。 STR_X1, STR_Y1 出现两次,STR_X2, STR_Y2 只出现一次(即没有平局决议)x11aa
很简单,只有一行x21ab
,两个组合都有 1 行,但 STR_X4, STR_Y4 是最新的。 代码
这是我到目前为止所拥有的:
def reducer(id_group):
id_with_sizes = id_group.groupby(
["id", "string_col_A", "string_col_B"], dropna=False).agg({
'creation_date': [len, max]
}).reset_index()
id_with_sizes.columns = [
"id", "string_col_A", "string_col_B", "row_count",
"recent_date"
]
id_with_sizes.sort_values(by=["row_count", "recent_date"],
ascending=[False, False],
inplace=True)
return id_with_sizes.head(1).drop(["recent_date", "row_count"], axis=1)
我像这样调用上述方法:
assignment = all_data.groupby("id").apply(inventor_reduce)
问题
上面的代码在测试数据时工作正常,但我正在使用的实际数据集有超过 1000 万行,大约有 300 万个 ID。 因此,处理 10K IDS 需要 5 分钟,总共需要 25 小时来处理。 我想提高性能。
解决方案
我在 stackoverflow(和其他地方)上看到了关于获得频繁组合(尽管没有领带解决方案)和关于对过程进行矢量化以提高性能的问题。 我不太确定如何解决我上面的问题。
理想情况下,解决方案仍然是基于熊猫的(使用熊猫代码看起来和阅读起来更好)
s
,结合两列.groupby
代码中取出, sort=False
并在最后进行排序。——
s = df['string_col_A'] + df['string_col_B']
df['max'] = df.groupby(['id',s])['id'].transform('count')
df = df.iloc[df.groupby('id', sort=False)['max'].idxmax().values].drop(['max', 'creation_date'], axis=1)
df
Out[1]:
id string_col_A string_col_B
0 x12ga STR_X1 STR_Y1
3 x21ab STR_X4 STR_Y4
5 x11aa STR_X3 STR_Y3
您只需要按id
列进行分组,并基于此找到最常用的数据(模式)。
为了使事情更容易,您可以创建另一列combined_str
:
df['combined_str'] = df['string_col_A'] + df['string_col_B']
id
分组并使用pd.Series.mode
函数减少:df = df.sort_values(by=['creation_date'])
df = df.groupby(['id'])['combined_str'].agg(most_common = ('combined_str', pd.Series.mode))
让我们尝试groupby
和transform
,然后获取最常见值的计数,然后sort_values
和drop_duplicates
df['help'] = df.groupby(['id','string_col_A','string_col_B'])['string_col_A'].transform('count')
out = df.sort_values(['help','creation_date'],na_position='first').drop_duplicates('id',keep='last').drop(['help','creation_date'],1)
out
Out[122]:
id string_col_A string_col_B
3 x21ab STR_X4 STR_Y4
5 x11aa STR_X3 STR_Y3
0 x12ga STR_X1 STR_Y1
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.