簡體   English   中英

pandas:根據其他列將多行中一個單元格的值替換為一個特定行

[英]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 這意味着您可以使用groupbytransform獲取每個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 ,它們會有所不同

使用groupbymap

假設是對於最小的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.

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