簡體   English   中英

將 dataframe 中的多行與單行逐列進行比較

[英]Comparing multiple rows in dataframe to single row by column

假設我有一個 dataframe 如下所示:

user       email                  day_diff  

tom        tommy@email.com         -10
tom        thomas@email.com        -2
tom        tom@email.com            3
bob        bob123@email.com        -11
bob        bob123@email.com         1
bob        bobby@email.com          2
alice      alice@email.com          4
Mary       mary@email.com          -5

我要做的是為每個用戶獲取每個 email,其中 day_diff 為正數,第一個記錄 day_diff 為負數但最接近 0。然后比較這些值,如果它們中的任何一個不同,則在新列中該值將 '是',如果它們都相同,則值為'否'

因此,對於 tom,我將采用 email,其中 day_diff 為 3,tom@email.com,因為它是唯一的正 day_diff,並將其與 thomas@email.Z4D236D9A20D102C5ZFE6ADC1 進行比較由於不同,tom 每一行的新列將是“是”

對於 bob,我會使用 day_diff 為 1 和 2 的電子郵件並將其與 -11 進行比較。 由於 2 和 -11 處的 email 不同,因此新列值為“是”。

如果用戶只有一行並且 day_diff 為正,則新列值為 'yes' 如果用戶只有 day_diff 為負的電子郵件,則新列值為 'no'

任何幫助,將不勝感激。 我一直在轉圈試圖弄清楚這一點。

output 看起來像

user       email                  day_diff    email_change

tom        tommy@email.com         -10        yes
tom        thomas@email.com        -2         yes
tom        tom@email.com            3         yes
bob        bob123@email.com        -11        yes
bob        bob123@email.com         1         yes
bob        bobby@email.com          2         yes
alice      alice@email.com          4         yes
Mary       mary@email.com          -5         no

這是我的建議:

import pandas as pd
import numpy as np

df = pd.DataFrame({"user": ["tom", "tom", "tom", "bob", "bob", "bob", "alice", "mary"],
                   "email": ["tommy@email.com", "thomas@email.com", "tom@email.com", "bob123@email.com",
                             "bob123@email.com", " bobby@email.com", "alice@email.com", "mary@email.com"],
                   "day_dif": [-10, -2, 3, -11, 1, 2, 4, -5]})

# Treat case where no duplicates
df["dup"] = df["user"].duplicated(keep=False)
df["output"] = np.select([(df["dup"] == False) & (df["day_dif"] > 0), 
                          (df["dup"] == False) & (df["day_dif"] < 0)],
    ["yes", "no"], default=np.NaN)

# Treat duplicates
temp = df.loc[df["dup"], :]
temp = temp.copy()
temp["neg"] = np.where(temp["day_dif"] < 0, temp["day_dif"], np.NaN)
idx = temp.groupby("user")["neg"].nlargest(1).reset_index().level_1
# Create grouping variable that will help us make comparison
temp["pos"] = np.where(temp.index.isin(idx), 1,(temp["day_dif"] > 0) * 1)

groups = (temp.groupby(['user', "pos"])["email"].apply(list).reset_index()
              .sort_values(["user", "pos"]))
# compare all email in list by user and group pos
groups["output"] = groups["email"].apply(lambda x: all(w == x[0] for w in x))
# put on same line value for pos = 0 and pos = 1 for each user
groups["temp"] = groups["output"].shift(periods=-1)

# Apply your rules
groups["output"] = np.select([(groups.pos == 1) & (groups["output"] == False),
                              (groups.pos == 0) & (groups["temp"] == False)],
    ["yes", "yes"], default="no")
# reunite duplicates and non duplicates in one dataframe
new_df = pd.merge(df.loc[:, ["user", "email", "day_dif", "output"]],
                  groups[["user", "email", "output"]].explode(column="email"), 
                  on=["user", "email"], how="outer")
new_df["output"] = np.where(new_df["output_y"].isnull(), 
                            new_df["output_x"], new_df["output_y"])
new_df = new_df.drop(columns=["output_x", "output_y"]).drop_duplicates()

output 是:

   user             email  day_dif output
0    tom   tommy@email.com      -10    yes
1    tom  thomas@email.com       -2    yes
2    tom     tom@email.com        3    yes
3    bob  bob123@email.com      -11    yes
5    bob  bob123@email.com        1    yes
7    bob   bobby@email.com        2    yes
8  alice   alice@email.com        4    yes
9   mary    mary@email.com       -5     no

暫無
暫無

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

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