簡體   English   中英

如何使用 Python 將 CSV 中的重復項添加到多個實例的特定行的末尾?

[英]How do I add duplicates from a CSV to the end of a specific row over several instances using Python?

我有兩個要合並的 CSV,一個看起來像這樣(有更多客戶)

下面的表格和 csv 已與“后續問題”中示例的原始版本不同。 Stack Overflow 一直不接受對配置文件和事件表的編輯,但下面的 csv 是正確的。

配置文件表 ( df_profiles )

ID 姓名 Email
12 麥克風 邁克@AOL.com
78 簡@AOL.com

另一個看起來像這樣(還有更多事件)

事件表 ( df_events )

ID 姓名 事件類型 活動日期
12 麥克風 升級 20 年 10 月 2 日
78 升級 20 年 9 月 18 日
12 麥克風 取消 20 年 10 月 30 日
12 麥克風 升級 20 年 11 月 25 日
78 取消 20 年 11 月 14 日

最后,我希望最終的 CSV 導出看起來像這樣(有更多的客戶和事件)

ID 姓名 Email 事件類型 1 活動日期 1 事件類型 2 活動日期 2 事件類型 3 活動日期 3 事件類型 4 活動日期 4
12 麥克風 邁克@AOL.com 升級 2020 年 10 月 2 日 取消 2020 年 10 月 30 日 升級 2020 年 11 月 25 日 取消 2020 年 12 月 3 日
78 簡@AOL.com 升級 2020 年 9 月 18 日 升級 2020 年 10 月 30 日 取消 2020 年 11 月 14 日

這是我到目前為止所擁有的

    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 姓名 Email 事件類型 1 活動日期 1 事件類型 2 活動日期 2
12 麥克風 邁克@AOL.com 升級 20 年 10 月 2 日 取消 20 年 10 月 30 日
12 麥克風 邁克@AOL.com 升級 20 年 10 月 2 日 升級 20 年 11 月 25 日
78 簡@AOL.com 升級 20 年 9 月 18 日 取消 20 年 11 月 14 日

因此,它沒有將其添加到第三個事件中,而是創建了另一列。 這只是一個示例,實際上許多用戶有 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

配置文件.csv

ID,NAME,email
12,Mike,Mike@AOL.com
78,Jane,Jane@AOL.com

跟進問題

在 anky 的幫助下,我找到了一個解決方案,它產生了我正在尋找的東西,但是,我想清除一個格式障礙,這將使我在執行該項目的 rest 時更輕松。

output 表將事件類型全部分組在一起,並在這些分組中按日期對它們進行排序。 例如,輸出如下所示:

ID 姓名 Email 事件類型 1 活動日期 1 事件類型 2 活動日期 2 事件類型 3 活動日期 3 事件類型 4 活動日期 4
12 麥克風 邁克@AOL.com 取消 20 年 10 月 30 日 取消 20 年 12 月 3 日 升級 20 年 10 月 2 日 升級 20 年 11 月 25 日
78 簡@AOL.com 取消 20 年 11 月 14 日 升級 20 年 9 月 18 日 升級 20 年 10 月 30 日

與預期的 output 相比(如上圖):

ID 姓名 Email 事件類型 1 活動日期 1 事件類型 2 活動日期 2 事件類型 3 活動日期 3 事件類型 4 活動日期 4
12 麥克風 邁克@AOL.com 升級 2020 年 10 月 2 日 取消 2020 年 10 月 30 日 升級 2020 年 11 月 25 日 取消 2020 年 12 月 3 日
78 簡@AOL.com 升級 2020 年 9 月 18 日 升級 2020 年 10 月 30 日 取消 2020 年 11 月 14 日

為了確保我沒有弄亂我的日期排序,我進入 CSV 本身並按日期正確排序事件,我仍然得到 output 按事件而不是日期分組。 我在下面重新發布我的代碼,以防我出錯。

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 進行分組並創建一個索引,然后我們使用 pivot 使用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 姓名 Email 活動日期 1 事件類型 1 活動日期 2 事件類型 2 活動日期 3 事件類型 3
0 12 麥克風 邁克@AOL.com 20 年 10 月 2 日 升級 20 年 10 月 30 日 取消 20 年 11 月 25 日 升級
1 78 簡@AOL.com 20 年 9 月 18 日 升級 20 年 11 月 14 日 取消

編輯:

根據已編輯的問題,我們可以嘗試將日期字段轉換為日期時間並進行 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 姓名 email 活動日期 1 事件類型 1 活動日期 2 事件類型 2 活動日期 3 事件類型 3 活動日期 4 事件類型 4
0 12 麥克風 邁克@AOL.com 2020 年 10 月 2 日 升級 2020 年 10 月 30 日 取消 2020 年 11 月 25 日 升級 2020 年 12 月 3 日 取消
1 78 簡@AOL.com 2020 年 9 月 18 日 升級 2020 年 10 月 30 日 升級 2020 年 11 月 14 日 取消

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM