如何将每行列表中的元素与熊猫匹配

Posted

技术标签:

【中文标题】如何将每行列表中的元素与熊猫匹配【英文标题】:How to match elements in lists in every row with pandas 【发布时间】:2021-07-28 21:58:34 【问题描述】:

我有一个包含 3 列的数据框。 ID、日期和建议。推荐是包含每天多个值的列表列。我想为每个 ID 找到与 day d 和 day d+1 匹配的推荐。数据框如下所示。

| ID | Date       | Recommendations |
| 1  | 1/1/2021   | [A, B, C]       |
| 1  | 1/2/2021   | [A, F, C]       |
| 1  | 1/3/2021   | [A, B, D]       |
| 2  | 1/13/2021  | [A, B, C]       |
| 2  | 1/14/2021  | [A, B, C]       |
| 2  | 1/15/2021  | [A, H, C]       |

我希望结果如下所示

| ID | Date       | Recommendations | Match |
| 1  | 1/1/2021   | [A, B, C]       | 2     |
| 1  | 1/2/2021   | [A, F, C]       | 1     |
| 1  | 1/3/2021   | [A, B, D]       | 0     |
| 2  | 1/13/2021  | [A, B, C]       | 3     |
| 2  | 1/14/2021  | [A, B, C]       | 2     |
| 2  | 1/15/2021  | [A, H, C]       | 0     | 

计算应在 ID 级别进行。因此,所有 ID 的最后一个值为 0。 日期可能并不总是被排序,但我希望在匹配建议之前对其进行排序。在python中有没有一种有效的方法来做到这一点?我有接近 5M 行。

【问题讨论】:

【参考方案1】:

ALollz 的答案非常聪明和 Python。一个更“蛮力”的答案是在组内切换以获取每个用户的未来几天推荐,然后使用集合交集运算符简单地比较两列:

df["recommendations_next_day"] = df.groupby(by='ID')['Recommendations'].shift(-1)

df["Recommendations"] = df.Recommendations.apply(set)
df["recommendations_next_day"]= df.recommendations_next_day.apply(lambda x: set(x) if x==x else set())
df["count"]= df[["Recommendations","recommendations_next_day"]].apply(lambda x: len(x[0] & x[1]) 
                    ,axis =1)

当然,这里假设DF按ID排序,然后是日期,每天都有记录。

【讨论】:

【参考方案2】:

将您的日期列转换为datetime 然后explode 列表。然后通过将这个爆炸的 DataFrame 与其自身合并(我们从日期中减去 1 天),我们只保留相同 ID 内的行,这些行在 Date 和 Date+1day 上具有相同的建议。取大小,按原始索引分组,使用匹配列,我们可以分配回(因为对齐在索引上)

import pandas as pd

df['Date'] = pd.to_datetime(df['Date'], format='%m/%d/%Y')

df1 = df.explode('Recommendations').reset_index()
df1 = df1.merge(df1.drop(columns='index').assign(Date=df1['Date']-pd.offsets.DateOffset(days=1)))

df['match'] = df1.groupby('index').size()
df['match'] = df['match'].fillna(0, downcast='infer')

   ID       Date Recommendations  match
0   1 2021-01-01       [A, B, C]      2
1   1 2021-01-02       [A, F, C]      1
2   1 2021-01-03       [A, B, D]      0
3   2 2021-01-13       [A, B, C]      3
4   2 2021-01-14       [A, B, C]      2
5   2 2021-01-15       [A, H, C]      0

【讨论】:

这里不计算第 d 天和 d+1 天两个列表中匹配的元素个数。这是一个很好的方法,但没有预期的答案。不过谢谢。 @SudhakarSamak 我不明白你的评论,因为这个解决方案完全正确。如果您的真实数据在推荐列表中有重复,或者在 [ID, Date] 上重复,那么它可能与您的预期不同,但那是因为您似乎想要逐行比较,尽管指定了第二天。 并且需要明确的是,这会明确检查后续天数,您接受的解决方案只关心后续行,无论它们之间是否有 1 天或 10 天(在 ID 内)。

以上是关于如何将每行列表中的元素与熊猫匹配的主要内容,如果未能解决你的问题,请参考以下文章

使用熊猫将列表中的单词与频率列表中的单词进行比较

如何将列表中的值分配给熊猫数据框并控制每个列表元素在数据框中的分布/频率

如何将包含数组中的值的熊猫列扩展到多列?

从列A数据框A到数据框B中的C的匹配值,并使用熊猫从数据框A创建不匹配的列表

从熊猫字典列表中提取元素

如何使用熊猫对与给定条件匹配的列中的值求和?