python - pandas 嵌套迭代的矢量化解决方案

标签 python dataframe loops group-by iteration

给出一个示例数据框:


example_df = pd.DataFrame({"app_id": [1,2,3,4,5,6] ,
              "payment_date":["2021-01-01", "2021-02-01", "2020-03-02", "2020-04-05", "2020-01-05","2020-01-04"],
              "user_id": [12,12,12,13,13,13], 
              "application_date":["2021-02-01", "2021-02-01", "2020-03-02", "2020-04-05", "2020-01-05", "2020-01-04"] , "flag": [1,0,0,1,0,1], "order_column": [1,2,3,4,5, 6]})

应该做的是:

  • 我将用一个例子来解释我想要做什么:
  • 迭代所有行
  • 如果标志列等于 1,请执行以下操作
  • 对于第一行,flag 列为 1,该行的 user_id 为 12。查看 user_id= 12 的所有实例,并且将他们的 application_date 与第一行的 payment_date 进行比较。我们看到第二行的 application_date 大于第一行的 payment_date 。那么第一行的标签是1。第三行也属于user_id= 12,但它的application_date不大于第一行的 payment_date。如果有一个或多个观测值的 application_date 大于第一行的 payment_date,则第一行的整体标签为 1。如果没有此类观测值,则整体标签为 1是 0。

我用 iterrows 编写了代码,但我想要一个更紧凑的矢量化解决方案,因为 iterrows 对于较大的数据集可能会很慢。喜欢

example_df.groupby("something").filter(lambda row: row. ...)


我的代码是:


labels_dict = {}
for idx, row in example_df.iterrows():
    if row.flag == 1:
        app_id = row.app_id
        user_id = row.user_id
        user_df = example_df[example_df.user_id == user_id]
        labelss = []
        for idx2, row2 in user_df.iterrows():
            if (row2.order_column != row.order_column) & (row.payment_date < row2.application_date):
                label = 1
                labelss.append(label)
            elif (row2.order_column != row.order_column) & (row.payment_date >= row2.application_date):
                label = 0
                labelss.append(label)
        labels_dict[app_id] = labelss

final_labels = {}
for key, value in labels_dict.items():
    if 1 in value:
        final_labels[key] = 1
    else:
        final_labels[key] = 0

final_labels 是预期的输出。基本上,我要求根据我解释的标准,将 flag= 1 的所有行标记为 1 或 0。

期望的输出:

{1: 1, 4: 0, 6: 1}

Here keys are app_id and values are labels (either 0 or 1)

最佳答案

我首先构建一个临时数据帧,其中 flag 中仅有 1 行,并将其与 user_id 上的完整数据帧合并。

然后,如果 application_date 大于 payment_date 并且原始 app_id 与 temp 上的 on from temp 不同(即不同的行),我将添加一个新的 bool 列,该列为 true

最后,计算每个 app_id 的真实值数量就足够了,如果数量大于 0,则给出 1。

Pandas 代码可能是:

tmp = example_df.loc[example_df['flag'] == 1,
                     ['app_id', 'user_id', 'payment_date']]

tmp = tmp.merge(example_df.drop(columns = 'payment_date'), on='user_id')

tmp['k'] = ((tmp['app_id_x'] != tmp['app_id_y'])
            & (tmp['application_date'] > tmp['payment_date']))

d = (tmp.groupby('app_id_x')['k'].sum() != 0).astype('int').to_dict()

根据您的数据,它会按预期给出:

{1: 1, 4: 0, 6: 1}

关于python - pandas 嵌套迭代的矢量化解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70799270/

相关文章:

python - 如何让 Python 输入循环读取和更新列表项

python - 在不同的整数类型中保存相同的值有什么区别吗?

javascript - 使用scrapy抓取动态网页数据

python - 向 pandas 数据框添加分组、聚合的 nunique 列

在 R : rows to columns 中 reshape 数据框

c - 使用结构体组织输入 - C 编程

python - while循环不会停止循环

python - 如何单击一个元素,然后使用它来更改另一个元素

python - 有没有一种简单的方法来 pickle 一个 python 函数(或者序列化它的代码)?

python - Pandas 数据框基于日期范围的条件累积和