python - 如何使用 Python 在多个实例中将 CSV 中的重复项添加到特定行的末尾?

标签 python pandas csv duplicates

我有两个我想合并的 CSV,一个看起来像这样(有更多的客户)
下面的表格和 csv 与“后续问题”中示例的原始版本有所不同。 Stack Overflow 一直不接受对配置文件和事件表的编辑,但下面的 csv 是正确的。
配置文件表 ( df_profiles )


ID
姓名
电子邮件


12
麦克风
迈克@AOL.com

78

简@AOL.com


另一个看起来像这样(有更多的事件)
事件表 ( df_events )


ID
姓名
事件类型
事件日期


12
麦克风
升级
10/02/20

78

升级
9/18/20

12
麦克风
取消
10/30/20

12
麦克风
升级
11/25/20

78

取消
11/14/20


最后,我希望最终的 CSV 导出看起来像这样(有更多的客户和事件)


ID
姓名
电子邮件
事件类型 1
事件日期 1
事件类型 2
事件日期 2
事件类型 3
事件日期 3
事件类型 4
事件日期 4


12
麦克风
迈克@AOL.com
升级
10/2/2020
取消
10/30/2020
升级
11/25/2020
取消
12/03/2020

78

简@AOL.com
升级
2020/9/18
升级
10/30/2020
取消
11/14/2020



这是我到目前为止

    import pandas as pd

    df_profiles = pd.read_csv('profiles.csv')
    df_events = pd.read_csv('events.csv')

    df_merge = pd.merge(df_profiles[['ID', 'NAME', 'email']], df_events[['ID', 'Event Type', 'Event Date']], on='ID', how='outer')
    df_duplicates = df_merge[df_merge.duplicated('ID')]
    df_stitch = pd.merge(df_merge, df_duplicates[['ID', 'Event Type', 'Event Date']], on='ID')
这会像这样输出表格


ID
姓名
电子邮件
事件类型 1
事件日期 1
事件类型 2
事件日期 2


12
麦克风
迈克@AOL.com
升级
10/02/20
取消
10/30/20

12
麦克风
迈克@AOL.com
升级
10/02/20
升级
11/25/20

78

简@AOL.com
升级
9/18/20
取消
11/14/20


因此,它没有将其添加到第三个事件中,而是创建了另一列。这只是一个例子,实际上许多用户有 10 多个事件,但有些用户只有 1 或 2 个。我确信解决方案只是一个特定的循环,但我似乎无法找到一个有效的循环。任何帮助将不胜感激,在此先感谢您。
文件内容如下图:
事件.csv
ID,NAME,Event Type,Event Date,email
12,Mike,upgrade,10/2/2020,Mike@AOL.com
78,Jane,upgrade,9/18/2020,Jane@AOL.com
12,Mike,cancel,10/30/2020,Mike@AOL.com
12,Mike,upgrade,11/25/2020,Mike@AOL.com
78,Jane,cancel,11/14/2020,Jane@AOL.com
12,Mike,cancel,12/03/2020,Mike@AOL.com
78,Jane,upgrade,10/30/2020,Jane@AOL.com
profile.csv
ID,NAME,email
12,Mike,Mike@AOL.com
78,Jane,Jane@AOL.com
跟进问题
在 anky 的帮助下,我找到了一个解决方案,它产生了我想要的东西,但是,我想清除一个格式障碍,这将使我在完成该项目的其余部分时更轻松。
输出表将事件类型分组在一起,并在这些分组中按日期对它们进行排序。例如,输出如下所示:


ID
姓名
电子邮件
事件类型 1
事件日期 1
事件类型 2
事件日期 2
事件类型 3
事件日期 3
事件类型 4
事件日期 4


12
麦克风
迈克@AOL.com
取消
10/30/20
取消
12/03/20
升级
10/2/20
升级
11/25/20

78

简@AOL.com
取消
11/14/20
升级
9/18/20
升级
10/30/20



与预期的输出(如上所示):


ID
姓名
电子邮件
事件类型 1
事件日期 1
事件类型 2
事件日期 2
事件类型 3
事件日期 3
事件类型 4
事件日期 4


12
麦克风
迈克@AOL.com
升级
10/2/2020
取消
10/30/2020
升级
11/25/2020
取消
12/03/2020

78

简@AOL.com
升级
2020/9/18
升级
10/30/2020
取消
11/14/2020



为了确保我没有弄乱我的日期排序,我进入了 CSV 本身并按日期正确排序事件,我仍然得到按事件而不是日期分组的输出。我在下面重新发布我的代码,以防我犯了错误。
import pandas as pd

df_profiles = pd.read_csv('profiles.csv')
df_events = pd.read_csv('events.csv')
df_events = df_events[['ID','Event Type','Event Date','NAME','email']]
df_profiles = df_profiles[['ID','NAME','email']]

events = df_events.groupby('ID')['Event Type'].apply(lambda x: x.ne(x.shift).cumsum())

out = (df_profiles.merge(df_events.drop(['NAME','email'],1).assign(Events=events),on='ID',how='outer')
        .pivot_table(index=['ID','NAME','email'],columns='Events',aggfunc='first')
        .sort_index(axis=1,level=1))

out.columns = out.columns.map('{0[0]} {0[1]}'.format)
out = out.reset_index()

out.to_csv('testingfinal.csv',index=False,encoding='utf-8-sig')

最佳答案

您可以使用以下内容动态转置事件类型和日期。这使用了一个辅助列,它根据 ID 进行分组并创建一个索引,然后我们使用 df.pivot_table 进行透视。 .

events = df_events.groupby("ID")['Event Type'].apply(lambda x: x.ne(x.shift).cumsum())

out = (df_profiles.merge(df_events.drop("Name",1).assign(Events=events),on='ID')
        .pivot_table(index=['ID','Name','Email'],columns='Events',aggfunc='first')
        .sort_index(axis=1,level=1))

out.columns = out.columns.map('{0[0]} {0[1]}'.format)
out = out.reset_index()
print(out)



ID
姓名
电子邮件
事件日期 1
事件类型 1
事件日期 2
事件类型 2
事件日期 3
事件类型 3


0
12
麦克风
迈克@AOL.com
10/02/20
升级
10/30/20
取消
11/25/20
升级

1
78

简@AOL.com
9/18/20
升级
11/14/20
取消
NaN
NaN


编辑:
根据编辑过的问题,我们可以尝试将日期字段转换为 datetime 和 argsort ,然后使用相同的代码:
u = df_events.loc[pd.to_datetime(df_events['Event Date'],format='%m/%d/%Y').argsort()]

events = u.groupby('ID')['Event Type'].apply(lambda x: x.ne(x.shift).cumsum())

out = (df_profiles.merge(u.drop(['NAME','email'],1).assign(Events=events),
         on='ID',how='outer')
        .pivot_table(index=['ID','NAME','email'],columns='Events',aggfunc='first')
        .sort_index(axis=1,level=1))

out.columns = out.columns.map('{0[0]} {0[1]}'.format)
out = out.reset_index()
print(out)



ID
姓名
电子邮件
事件日期 1
事件类型 1
事件日期 2
事件类型 2
事件日期 3
事件类型 3
事件日期
4 事件类型 4


0
12
麦克风
迈克@AOL.com
10/2/2020
升级
10/30/2020
取消
11/25/2020
升级
12/03/2020
取消

1
78

简@AOL.com
2020/9/18
升级
10/30/2020
升级
11/14/2020
取消
NaN
NaN

关于python - 如何使用 Python 在多个实例中将 CSV 中的重复项添加到特定行的末尾?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65496213/

相关文章:

Python变量处理,我不明白

python Pandas : Find Sum of Column Based on Value of Two other Columns

python - 绘制 Pandas 数据框的饼图和表格

python - 如何在不使用任何模块或导入 CSV 的情况下从 CSV 文件创建字典?

php - 将 csv 文件导入数据库 - 带逗号的值

java.lang.ArrayIndexOutOfBoundsException : 5 WHILE LOOP

Python Sprite 宝可梦游戏 While 循环

python - 如何使用列表理解打印输出并保存在文件中?

python - 识别 pandas 列中的某些单词

python - 使用 anyio.TaskGroup 和 fastapi.StreamingResponse