【问题标题】:Fastest way to combine two slices from two pandas dataframes in a loop?在循环中组合来自两个熊猫数据帧的两个切片的最快方法?
【发布时间】:2018-08-07 06:03:59
【问题描述】:

我有一个人员 ID 列表,对于每个 ID,我想从两个不同的数据框中提取所有可用信息。另外,信息的种类也有ID,我只想要每个人ID的具体信息ID。以下是我目前的做法:

    new_table = []
    for i in range(ranges):

        slice = pd.concat([df1[sp.logical_and(df1.person.values == persons[i],
                                                   df1['info_id'].isin(info_ids))],
                df2[sp.logical_and(df2.person.values == persons[i],
                                      df2['info_id'].isin(info_ids))]], ignore_index=True)

        if len(list(set(slice['info_ids']))) < amount_of_info_needed:
                    continue
        else:
            full_time_range = max(slice['age_days']) - min(slice['age_days']) 
            if full_time_range <= 1460:
                new_table.append(slice)
            else:
                window_end = min(slice['age_days']) + 1460
                slice = slice[slice.age_days < window_end+1]
                if len(list(set(slice['info_id']))) < amount_of_info_needed:
                    continue
                else:
                    new_table.append(slice)
    #return new_table
    new_table = pd.concat(new_table, axis=0)
    new_table = new_table.groupby(['person', 'info_id']).agg(np.mean).reset_index()
    new_table.to_sql('person_info_within4yrs', engine, if_exists='append', index=False, 
                 dtype={'person': types.NVARCHAR(32), 'value': types.NVARCHAR(4000)})

我读到由于二次时间而没有在循环中使用 pd.concat,但我尝试将数据帧转换为数组并切片和连接它们,但这比使用 pd.concat 还要慢。在使用 %lprun 分析每一行之后,所有时间都被循环中的 pd.concat/logical_and 操作所消耗。此代码也比将 .loc 与两个数据帧一起使用并将两个切片连接在一起更快。在 if-else 块之后,我附加到一个列表,最后将列表变成一个数据框。

编辑:这是我正在做的一个例子。目标是按 person_id 和 info_id 从两个数据帧中切片,组合切片,并将组合切片附加到列表中,然后我将其转换回数据帧并导出到 SQL 表。 if-else 块也很重要,但根据我的分析,它们几乎不需要任何时间,所以我不打算详细描述它们。

df1.head()
    person  info_id value   age_days
0   000012eae6ea403ca564e87b8d44d0bb    0   100.0   28801
1   000012eae6ea403ca564e87b8d44d0bb    0   100.0   28803
2   000012eae6ea403ca564e87b8d44d0bb    0   100.0   28804
3   000012eae6ea403ca564e87b8d44d0bb    0   100.0   28805
4   000012eae6ea403ca564e87b8d44d0bb    0   100.0   28806

df2.head()
    person  info_id value   age_days
0   00000554787a3cb38131c3c38578cacf    4v  97.0    12726
1   00000554787a3cb38131c3c38578cacf    14v 180.3   12726
2   00000554787a3cb38131c3c38578cacf    9v  2.0 12726
3   00000554787a3cb38131c3c38578cacf    3v  20.0    12726
4   00000554787a3cb38131c3c38578cacf    0v  71.0    12726

【问题讨论】:

  • 请发布几行所有数据框。另外,为什么不 mergesubset cols by ID?
  • 欢迎来到 SO!请提供样本数据。参考这个帖子:stackoverflow.com/questions/20109391/…
  • 我尝试了迭代合并,但速度较慢,但​​您是否建议在开始时合并两个数据帧并仅从一个数据帧切片?

标签: python pandas


【解决方案1】:

我接受了 Parfait 的建议,首先将两个数据框连接成一个,然后一位同事给了我一个解决方案来遍历数据框。数据框由约 1.17 亿行和约 24.6 万个人 ID 组成。我同事的解决方案是创建一个字典,其中每个键都是一个人员 ID,每个键的值是数据框中该人员 ID 的行索引列表。然后,您可以使用 .iloc 通过引用字典中的值来切片数据帧。一小时左右跑完。

idx = df1['person'].reset_index().groupby('person')['index'].apply(tuple).to_dict()

for i in range(ranges):
    mrn_slice = df1.iloc[list(idx.values()[i])]

【讨论】:

    猜你喜欢
    • 2018-09-04
    • 2021-02-25
    • 2018-10-12
    • 2021-09-12
    • 1970-01-01
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    相关资源
    最近更新 更多