Python与tieresolution性能的结合最为频繁

2024-10-02 10:18:37 发布

您现在位置:Python中文网/ 问答频道 /正文

数据
我有一个看起来像这样的数据集:

| 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          |  

目标

  1. 我想为每个id找到最频繁的值组合
  2. 此外,在tie的情况下,我想提取最新的组合

即上表的结果为:

| id    | string_col_A | string_col_B |
|-------|--------------|--------------|
| x12ga | STR_X1       | STR_Y1       |
| x21ab | STR_X4       | STR_Y4       |
| x11aa | STR_X3       | STR_Y3       |

解释

  1. 对于x12ga,解释很简单。STR_X1,STR_Y1出现两次,STR_X2,STR_Y2只出现一次(即,无tie分辨率)
  2. x11aa也很简单,只有一行
  3. 对于x21ab,两个组合都有一行,但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)

问题
当使用数据进行测试时,上面的代码工作得很好,但我正在使用的实际数据集有超过10M行,ID约为3M。因此,处理10K ID需要5分钟,总体上需要25小时。我想提高性能

解决方案
我在stackoverflow(和其他地方)上看到过关于获得频繁组合(尽管没有tie分辨率)和关于矢量化流程以提高性能的问题。我不太清楚如何实现这两个与我的问题以上

理想情况下,解决方案仍然是基于pandas的(pandas使代码看起来和读起来更好)


Tags: 数据iddatestringwithcolx1sizes
3条回答
  1. 您可以创建一个组合两列的系列s
  2. 返回最大计数的索引
  3. 按该索引过滤注意:如果您使用的是早期版本的pandas,则从.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

让我们尝试使用groupbytransform,然后获得最常见值的计数,然后使用drop_duplicatessort_values

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

您只需要按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))

相关问题 更多 >

    热门问题