[英]pandas: replace one cell's value from mutiple row by one particular row based on other columns
我的目標:
uniqueIdentity beginTime progrNumber
0 2018-02-07-6253554 17:40:29 1
1 2018-02-07-6253554 17:40:29 2
2 2018-02-07-6253554 17:40:29 3
3 2018-02-07-6253554 17:40:29 4
4 2018-02-07-6253554 17:40:29 5
5 2018-02-07-5555333 17:48:29 2
6 2018-02-07-5555333 17:48:29 3
7 2018-02-07-5555333 17:48:29 4
8 2018-02-07-2345622 18:40:29 1
9 2018-02-07-2345622 18:40:29 2
10 2018-02-07-2345622 18:40:29 3
11 2018-02-07-2345622 18:40:29 4
我現在的數據集:
uniqueIdentity beginTime progrNumber
0 2018-02-07-6253554 17:40:29 1
1 2018-02-07-6253554 17:41:15 2
2 2018-02-07-6253554 17:41:55 3
3 2018-02-07-6253554 17:42:54 4
4 2018-02-07-6253554 17:43:29 5
5 2018-02-07-5555333 17:49:15 2
6 2018-02-07-5555333 17:49:55 3
7 2018-02-07-5555333 17:50:54 4
8 2018-02-07-2345622 18:40:29 1
9 2018-02-07-2345622 18:41:15 2
10 2018-02-07-2345622 18:41:55 3
11 2018-02-07-2345622 18:42:54 4
這意味着:對於具有相同“uniqueIdentity”的行,“beginTime”應替換為具有相同“uniqueIdentity”的單元格的值,而“progrNumber”是最小的“progrNumber”。
正如您在評論中提到的,最低的progrNumber
也將是最低的beginTime
。 這意味着您可以使用groupby
和transform
獲取每個uniqueIdentity
的最低beginTime
。
請注意,如果beginTime
是字符串類型,則僅當它具有一致的格式時才有效。 (例如“09:40:20”而不是“9:40:20”)
df['beginTime'] = df.groupby('uniqueIdentity').beginTime.transform('min')
uniqueIdentity beginTime progrNumber
0 2018-02-07-6253554 17:40:29 1
1 2018-02-07-6253554 17:40:29 2
2 2018-02-07-5555333 17:48:29 3
3 2018-02-07-5555333 17:48:29 4
4 2018-02-07-6253554 17:40:29 3
5 2018-02-07-6253554 17:40:29 4
6 2018-02-07-5555333 17:48:29 1
7 2018-02-07-5555333 17:48:29 2
8 2018-02-07-2345622 18:40:29 1
9 2018-02-07-2345622 18:40:29 3
10 2018-02-07-2345622 18:40:29 4
這是使用左連接和一些重命名的另一個選項
# find rows where progrNumber is 1
df_prog1=df[df.progrNumber==1]
# do a left join on the original
df=df.merge(df_prog1,on='uniqueIdentity',how='left',suffixes=('','_y'))
# keep only the beginTime from the right frame
df=df[['uniqueIdentity','beginTime_y','progrNumber']]
# rename columns
df=df.rename(columns={'beginTime_y':'beginTime'})
print(df)
結果是:
uniqueIdentity beginTime progrNumber
0 2018-02-07-6253554 17:40:29 1
1 2018-02-07-6253554 17:40:29 2
2 2018-02-07-6253554 17:40:29 3
3 2018-02-07-6253554 17:40:29 4
4 2018-02-07-5555333 17:48:29 1
5 2018-02-07-5555333 17:48:29 2
6 2018-02-07-5555333 17:48:29 3
7 2018-02-07-5555333 17:48:29 4
8 2018-02-07-2345622 18:40:29 1
9 2018-02-07-2345622 18:40:29 2
10 2018-02-07-2345622 18:40:29 3
11 2018-02-07-2345622 18:40:29 4
如果您不確定uniqueIdentity
中的哪條記錄的時間最短,您可以使用groupby
而不是選擇 where progrNumber==1
:
df_prog1=df.groupby('uniqueIdentity')['beginTime'].min().reset_index()
並按照上面的方法進行左連接。
如果每個用戶的第一個beginTime
始終對應於每個用戶的最小程序編號,您可以執行以下操作:
d = df.groupby('uniqueIdentity')['beginTime'].first().to_dict()
df['beginTime'] = df['uniqueIdentity'].map(d)
為了更明確地獲取程序編號最小的時間(無論其位置如何),您將上面的d
替換為:
d = df.groupby('uniqueIdentity').apply(lambda x: x['beginTime'][x['progrNumber'].idxmin()]).to_dict()
這兩個對您的示例數據產生相同的結果,但如果有用戶的第一個beginTime
(或每個 Hugolmn 的最小beginTime
)不對應於用戶的最小progrNumber
,它們會有所不同
groupby
和map
假設是對於最小的progrNumber
來說beginTime
總是最小的。 根據問題的評論,此條件為真。
在這個答案中,我收集了每個uniqueIdentity
的最小 beginTime ,然后將 map 收集到基於 uniqueIdentity 的原始uniqueIdentity
。
times = df.groupby('uniqueIdentity').beginTime.min()
df['beginTime'] = df.uniqueIdentity.map(times)
如果我們不能假設 min progrNumber
也是 min beginTime
,則需要更復雜的方法:
df['beginTime'] = (
df.groupby('uniqueIdentity', as_index=False, group_keys=False)
.apply(lambda s: pd.Series(s[s.progrNumber==s.progrNumber.min()]
.beginTime.item(), index=s.index)
)
)
df
# uniqueIdentity beginTime progrNumber
# 0 2018-02-07-6253554 17:40:29 1
# 1 2018-02-07-6253554 17:40:29 2
# 2 2018-02-07-6253554 17:40:29 3
# 3 2018-02-07-6253554 17:40:29 4
# 4 2018-02-07-6253554 17:40:29 5
# 5 2018-02-07-5555333 17:49:15 2
# 6 2018-02-07-5555333 17:49:15 3
# 7 2018-02-07-5555333 17:49:15 4
# 8 2018-02-07-2345622 18:40:29 1
# 9 2018-02-07-2345622 18:40:29 2
# 10 2018-02-07-2345622 18:40:29 3
# 11 2018-02-07-2345622 18:40:29 4
如果您不想要單線器,則使用map
的方法將是理想的
mapping = (
df.groupby('uniqueIdentity')
.apply(lambda s: s[s.progrNumber==s.progrNumber.min()].beginTime.iloc[0])
)
df['beingTime'] = df.uniqueIdentity.map(mapping)
注意:如果您保證只有一個值具有最小progrNumber
,則可以將iloc[0]
替換為item()
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.