代码之家  ›  专栏  ›  技术社区  ›  Khris

Pandas:合并数据帧并仅保留与合并的唯一对关联的最小值

  •  1
  • Khris  · 技术社区  · 6 年前

    我对熊猫有一个更棘手的问题。

    V 它定义了群体。

    两个数据帧都有一个唯一的 ID Time 列。

    合并后,我计算 Timedelta 在这两列之间筛选出负值:

    import pandas as pd
    
    L11 = ['V1','V1','V1','V2','V2','V3','V3','V3','V3']
    L12 = [1,2,3,4,5,6,7,8,9]
    L13 = [pd.Timestamp("1.1.1980 12:12:12"),
           pd.Timestamp("1.1.1980 13:12:12"),
           pd.Timestamp("1.2.1980 01:12:12"),
           pd.Timestamp("1.1.1980 14:12:12"),
           pd.Timestamp("1.1.1980 16:12:12"),
           pd.Timestamp("1.1.1980 16:12:12"),
           pd.Timestamp("1.1.1980 14:12:12"),
           pd.Timestamp("1.1.1980 13:12:12"),
           pd.Timestamp("1.2.1980 10:12:12")]
    
    L21 = ['V1','V1','V2','V3','V3','V3','V3','V3','V3']
    L22 = [11,12,13,14,15,16,17,18,19]
    L23 = [pd.Timestamp("1.1.1980 12:12:12"),
           pd.Timestamp("1.1.1980 13:12:12"),
           pd.Timestamp("1.1.1980 14:12:12"),
           pd.Timestamp("1.1.1980 14:12:12"),
           pd.Timestamp("1.1.1980 16:12:12"),
           pd.Timestamp("1.1.1980 18:12:12"),
           pd.Timestamp("1.1.1980 11:12:12"),
           pd.Timestamp("1.1.1980 12:12:12"),
           pd.Timestamp("1.2.1980 10:12:12")]
    
    df1 = pd.DataFrame({'V':L11,'ID1':L12,'Time1':L13})
    df2 = pd.DataFrame({'V':L21,'ID2':L22,'Time2':L23})
    
    df = pd.merge(df1,df2,on='V')
    df["Delta"] = df.Time1-df.Time2
    df = df[df.Delta>pd.Timedelta(0)].copy()
    df = df.drop(["Time1","Time2"],axis=1)
    

    -在每个数据帧中都有一个组,并获取我调用的较低值 Max 身份证件 -每个值

    df1g = df1.groupby("V").ID1.count().reset_index().rename(columns={"ID1":"C1"})
    df2g = df2.groupby("V").ID2.count().reset_index().rename(columns={"ID2":"C2"})
    df12g = pd.merge(df1g,df2g,on='V')
    df12g["Max"] = df12g[["C1","C2"]].min(axis=1)
    df = pd.merge(df,df12g[['V','Max']],on='V')
    df = df.sort_values(['V','Delta']).reset_index(drop=True)
    

    这是我整理的示例数据:

         V  ID1  ID2    Delta  Max
    0   V1    2   11 01:00:00    2
    1   V1    3   12 12:00:00    2
    2   V1    3   11 13:00:00    2
    3   V2    5   13 02:00:00    1
    4   V3    8   18 01:00:00    4
    5   V3    6   14 02:00:00    4
    6   V3    7   18 02:00:00    4
    7   V3    8   17 02:00:00    4
    8   V3    7   17 03:00:00    4
    9   V3    6   18 04:00:00    4
    10  V3    6   17 05:00:00    4
    11  V3    9   16 16:00:00    4
    12  V3    9   15 18:00:00    4
    13  V3    9   14 20:00:00    4
    14  V3    9   18 22:00:00    4
    15  V3    9   17 23:00:00    4
    
    • V1 有3个条目,但只允许2个
    • 集团 V2
    • 集团 V3

    我现在需要为每个人找到 ID1 这个 ID2 Delta 但这些组合必须是唯一的。

    意思是因为 4 ID1 8 ID2 18 6 ID1 7 不能与 .

    我想要的结果基本上是:

         V  ID1  ID2    Delta  Max
    0   V1    2   11 01:00:00    2
    1   V1    3   12 12:00:00    2
    3   V2    5   13 02:00:00    1
    4   V3    8   18 01:00:00    4
    5   V3    6   14 02:00:00    4
    8   V3    7   17 03:00:00    4
    11  V3    9   16 16:00:00    4
    

    简单的方法

    df1 = df.drop_duplicates('ID1')
    df2 = df.drop_duplicates('ID2')
    result = pd.merge(df1,df2)
    

    如果不遍历已排序的行并构建已占用的内存,甚至可以解决这个问题吗 -价值观?

    1 回复  |  直到 6 年前
        1
  •  0
  •   Khris    6 年前

    回答我自己的问题 iterrows() 方法:

    df = df.sort_values(['V','Delta']).reset_index(drop=True)
    

    这就解决了问题:

    df["Keep"] = False
    old_V = ''
    for i,row in df.iterrows():
        if row.V != old_V:
            old_V = row.V
            ID1_list = []
            ID2_list = []
        if row.ID1 not in ID1_list and row.ID2 not in ID2_list:
            df.iloc[i,5] = True
            ID1_list.append(row.ID1)
            ID2_list.append(row.ID2)
    df = df[df.Keep].drop("Keep",axis=1)