【问题标题】:Create columns with match inside range from different dataframes in Pandas从 Pandas 中的不同数据框创建具有匹配范围内的列
【发布时间】:2020-08-07 14:46:44
【问题描述】:

我得到了两个包含几列的数据框,但这三个具有相似的数据。

Df1:
ID         Line    ...      Sta
19805       120    ...       30
19805       120    ...       40
19805       123    ...       30
    .       .       .         .
    .       .       .         .
19841       120    ...        30

Df2:
 ID         Line     ...      Sta
19805       122      ...       30
19805       119      ...       41
19805       123      ...       30
    .        .       .          .
    .        .       .          .
19841        120      ...      33

我想使用最接近 Df1 的匹配将两列添加到 Df2 与 Df1 的相同列

Df2:
 ID         Line     ...      Sta   linedf1   stadf1
19805       122      ...       30      120        30
19805       119      ...       41      120        40
19805       123      ...       30      123        30
    .        .        .         .       .         .
    .        .        .         .       .         .
19841        120      ...      33       120       30

注意,匹配需要在 Df2["Line"]+-4 和 Df2["Sta"]+-4 的范围内

所以我尝试了这个:

Df1["line"].where((Df2['line']-4)<=Df1["line"]) & (Df1["line"]<=(Df2['line']+4)

Df1.loc[((Df2['line']-4)<=Df1["line"]) & ((Df1["line"]<=(Df2['line']+4))]

Df1[Df1["line"].between((Df2['line']-4),(Df2['line']+4), inclusive= True)]

但所有这些都会导致此错误

ValueError: Can only compare identically-labeled Series objects

任何人都知道如何实现这一目标? 希望这个问题不要太含糊

【问题讨论】:

    标签: python pandas dataframe range


    【解决方案1】:

    首先使用DataFrame.merge

    df = df2.merge(df1, on='ID', suffixes=('', 'df1'))
    df = df[df["Line"].between((df['Linedf1']-4),(df['Linedf1']+4), inclusive= True)]
    print (df)
          ID  Line  Sta  Linedf1  Stadf1
    0  19805   122   30      120      30
    1  19805   122   30      120      40
    2  19805   122   30      123      30
    3  19805   119   41      120      30
    4  19805   119   41      120      40
    5  19805   119   41      123      30
    6  19805   123   30      120      30
    7  19805   123   30      120      40
    8  19805   123   30      123      30
    9  19841   120   33      120      30
    

    一种可能的解决方案是分块处理,每 N 行,创建最简单的 DataFrame 并最后连接在一起:

    #change to 10000 or 100000 in real data
    N = 3
    dfs = []
    for g, df11 in df1.groupby(np.arange(len(df1.index)) // N):
        df = df2.merge(df11, on='ID', suffixes=('', 'df1'))
        df = df[df["Line"].between((df['Linedf1']-4),(df['Linedf1']+4), inclusive= True)]
        #print (df)
        dfs.append(df)
    
    dfout = pd.concat(dfs, ignore_index=True)
    print (dfout)
          ID  Line  Sta  Linedf1  Stadf1
    0  19805   122   30      120      30
    1  19805   122   30      120      40
    2  19805   122   30      123      30
    3  19805   119   41      120      30
    4  19805   119   41      120      40
    5  19805   119   41      123      30
    6  19805   123   30      120      30
    7  19805   123   30      120      40
    8  19805   123   30      123      30
    9  19841   120   33      120      30
    

    【讨论】:

    • 感谢您提供此解决方案。不幸的是,由于 RAM 内存限制,这不起作用。 Df1 和 Df2 都是大型数据帧(df1 有 800k 行,df2 有 300k),并且在尝试此合并时超出了 google 的 colab 笔记本中允许的 RAM 内存(24 gb,比我笔记本电脑中的 4gb RAM 多得多)。我需要的是改进这些 DF 之间的合并。我已将这些 DF 与“ID”、“line”和“sta”的完全匹配合并,但这只会导致 40% 的完全匹配,因此需要与范围匹配。
    • @Rubén - 我有一个想法,答案已编辑。你能用你的真实数据来测试它吗?
    • 感谢 Jezrael,我实际上必须安装一个 SQL 管理器才能做到这一点(并请另一位 SQL 专家)。
    猜你喜欢
    • 2021-10-17
    • 1970-01-01
    • 2022-06-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多