【问题标题】:Filtering the dataframe based on the column value of another dataframe根据另一个数据框的列值过滤数据框
【发布时间】:2018-11-12 07:13:15
【问题描述】:

我有 2 个数据框

df1

Company           SKU   Sales
Walmart           A     100
Total             A     200
Walmart           B     200
Total             B     300
Walmart           C     400
Walmart           D     500

df2

 Company             SKU   Sales
 Walmart             A     400
 Total               B     300
 Walmart             C     900
 Walmart             F     400
 Total               G     500

我想要一个结果数据帧 (df2),它只包含 df1 和 df2 中匹配 SKU 的记录

df2

Company       SKU   Sales 
Walmart       A     400
Total         B     300
Walmart       C     900

我只想要 df2 中 df1 的唯一(公司 + SKU)值

有没有什么好的解决方案来实现这一点?

【问题讨论】:

    标签: python pandas filter merge


    【解决方案1】:

    更新

    你可以使用一个简单的掩码:

    m = df2.SKU.isin(df1.SKU)
    df2 = df2[m]
    

    您正在寻找内部连接。试试这个:

    df3 = df1.merge(df2, on=['SKU','Sales'], how='inner')
    
    #  SKU  Sales
    #0   A    100
    #1   B    200
    #2   C    300
    

    或者这个:

    df3 = df1.merge(df2, on='SKU', how='inner')
    
    #  SKU  Sales_x  Sales_y
    #0   A      100      100
    #1   B      200      200
    #2   C      300      300
    

    【讨论】:

    • 嗨 Anton,感谢您回答购买销售不是我的关键它可以是任何价值
    • @AhamedMoosa 我不明白你想要什么。我建议的当前解决方案可为您提供所需的结果。好的抱歉你改了名字
    • 您更新的答案符合我的目的谢谢。我可以将 isin 用于多个列吗?
    • @AhamedMoosa 抱歉回复晚了。您还在寻找如何在多个列上执行此操作的答案吗?
    • 我已经找到了解决此问题的方法,我使用了您的解决方案,并对我的用例进行了一些即兴创作。谢谢。
    【解决方案2】:

    一种方法是对齐索引,然后使用掩码。

    # align indices
    df1 = df1.set_index(['Company',  'SKU'])
    df2 = df2.set_index(['Company',  'SKU'])
    
    # calculate & apply mask
    df2 = df2[df2.index.isin(df1.index)].reset_index()
    

    不需要重置索引,但需要将CompanySKU 提升到列。

    【讨论】:

    • 谢谢 jpp ,我做了类似的事情。我已经连接了公司和 SKU 列,然后应用了掩码
    【解决方案3】:

    解决方案 1:

    # First identify the common SKU's    
    temp = list(set(list(df1.SKU)).intersection(set(list(df2.SKU))))
    
    # Filter df2 using the list of common SKU's
    df3 = df2[df2.SKU.isin(temp)]
    print(df3)
    
       SKU  Sales
    0   A   400
    1   B   300
    2   C   900
    

    解决方案 2:一条线解决方案

    df3 = df2[df2.SKU.isin(list(df1.SKU))]
    

    编辑 1:更新问题的解决方案(不是最佳方法,但回答您的问题)

    # reading data for df1
    df1= pd.read_clipboard(sep='\\s+')
    df1
        Company SKU Sales
    0   Walmart A   100
    1   Total   A   200
    2   Walmart B   200
    3   Total   B   300
    4   Walmart C   400
    5   Walmart D   500
    
    # reading data for df2
    df2= pd.read_clipboard(sep='\\s+')
    df2
    Company SKU Sales
    0   Walmart A   400
    1   Total   B   300
    2   Walmart C   900
    3   Walmart F   400
    4   Total   G   500
    
    # Using intersect and zip to create a list of tuples matching in the data frames
    temp = list(set(list(zip(df1.Company,df1.SKU))).intersection(set(list(zip(df2.Company,df2.SKU)))))
    temp
    [('Walmart', 'A'), ('Walmart', 'C'), ('Total', 'B')]
    
    # Creating a helper variable in df2 to lookup in the temp list
    df2["temp"] = list(zip(df2.Company,df2.SKU))
    df2= df2[df2["temp"].isin(temp)]
    del(df2["temp"])
    df2
        Company SKU Sales
    0   Walmart A   400
    1   Total   B   300
    2   Walmart C   900
    

    欢迎提出改进此代码的建议

    【讨论】:

    • 嗨,ram,谢谢你的回答以防万一我有多个列相交?
    • 然后您可以选择解决方案 1,因为 temp 是一个列表,您可以进一步与另一个列表相交。
    • 嗨拉姆,我已经编辑了我的问题,请告知您的第一个解决方案是否可以实现
    • 在我看来,list() 转换没有必要,而且可能很昂贵。
    • 完全同意你的看法。谢谢!
    猜你喜欢
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 2014-12-27
    • 2021-11-22
    相关资源
    最近更新 更多