【问题标题】:Conditionally filter rows in one df for specific columns which are common to subset of another df有条件地过滤一个df中的行以获取另一个df的子集共有的特定列
【发布时间】:2018-05-04 14:24:57
【问题描述】:

让我们假设一个 df1

 df1 = pd.DataFrame(
{'col1': {0: 500.0, 1: 500.0, 2: 833.3, 3: 500.0, 4: 833.3, 5: 500.0, 6: 833.3},
'col2': {0: 1833.3, 1: 1000.0, 2: 1833.3, 3: 2666.7, 4: 1833.3, 5: 3500.0, 6: 1000.0},
'col3': {0: 250.0, 1: 250.0, 2: 30.0, 3: 30.0, 4: 30.0, 5: 103.3, 6: 176.7},
'col4': {0: 3.4, 1: 4.0, 2: 2.2, 3: 3.4, 4: 2.2, 5: 4.0, 6: 3.4},
'col5': {0: 0.25, 1: 0.15, 2: 0.1, 3: 0.25, 4: 0.25, 5: 0.1, 6: 0.1},
'col6': {0: 364, 1: 937, 2: 579, 3: 313, 4: 600, 5: 49, 6: 13}})

还有一个 df2

 df2 = pd.DataFrame(
{'col1': {0: 833.3, 1: 500.0, 2: 500.0, 3: 500.0, 4: 500.0, 5: 500.0, 6: 500.0, 7: 833.3, 8: 500.0, 9: 833.3, 10: 500.0, 11: 500.0, 12: 833.3, 13: 833.3, 14: 833.3},
'col2': {0: 1833.3, 1: 1000.0, 2: 1833.3, 3: 3500.0, 4: 3500.0, 5: 1000.0, 6: 2666.7, 7: 1833.3, 8: 2666.7, 9: 1000.0, 10: 2666.7, 11: 2666.7, 12: 1000.0, 13: 1833.3, 14: 1833.3},
'col3': {0: 30.0, 1: 250.0, 2: 250.0, 3: 103.3, 4: 176.7, 5: 103.3, 6: 30.0, 7: 103.3, 8: 30.0, 9: 176.7, 10: 250.0, 11: 103.3, 12: 30.0, 13: 30.0, 14: 250.0},
'col4': {0: 2.2, 1: 4.0, 2: 3.4, 3: 4.0, 4: 2.2, 5: 2.8, 6: 2.8, 7: 2.8, 8: 3.4, 9: 3.4, 10: 2.8, 11: 2.8, 12: 3.4, 13: 2.2, 14: 2.8}, 
'col5': {0: 0.25, 1: 0.15, 2: 0.25, 3: 0.1, 4: 0.2, 5: 0.15, 6: 0.15, 7: 0.25, 8: 0.25, 9: 0.1, 10: 0.15, 11: 0.1, 12: 0.15, 13: 0.1, 14: 0.2}})

在 df2 中删除 col1 和 col2 以及 col3 和 col4(以及 coln )与 df1 的相应列具有相同值的行的最 Pythonic 方法是什么? 我不想合并数据框,只删除 df2 中的任何行(可能是多个),其中兴趣列上的行元组在两个 dfs 中是相同的。

我只是想出了如何使用:

new_df = df2.loc[df2[col1].isin(df1[col1]) &
              df2[col2].isin(df1[col2]) &
              df2[col3].isin(df1[col3]) &
              df2[col4].isin(df1[col4]) &
              df2[col5].isin(df1[col5]) ]

这对于更大的数据集和更多的列来说有点麻烦。

有什么更好的方法吗?

【问题讨论】:

  • 我试图要求澄清。目前我认为我还没有找到正确的答案。
  • 我现在明白了。主要问题是我们无法重现您的错误。描述很好,但是如果您能够edit 提出问题并举例说明问题(无论是温的还是我的,谁的都无所谓),那么真正 会有什么帮助。我已经用你的数据测试了我的解决方案,它似乎有效。
  • 我尝试将数据制作成易于复制的格式。希望这有助于找到更好的解决方案

标签: python python-3.x pandas dataframe


【解决方案1】:

您可以使用set_index 结合pd.Index.difference 来提取结果:

idx = df2.set_index(list(df2)).index\
         .difference(df1.set_index(list(df1)).index)

res = df2.set_index(list(df2)).loc[idx].reset_index()

这种方法的好处是它不需要数字到字符串的转换。

【讨论】:

  • 如果我们在每列中混合使用字符串和浮点数作为值,这是否也有效?另外,我们为什么要重置索引?我只需要删除行
  • 我们需要reset_index 以便索引再次变为行!带有索引但没有数据的数据框可能对您没有用。它应该适用于字符串和浮点数,但您应该使用您的数据进行测试。
  • ok 一些 cmets 。首先,它似乎有效。但是当两个 df 值之间不匹配时,我会丢失我的列名(它们变为 level_0、1 等)。另一个问题是这似乎有点慢。有没有更有效的方法?
【解决方案2】:

您可以使用isin,在此之前我们需要使用col1~ coln中的所有值创建一个键(转换为str并粘贴在一起)

df2[~df2[df1.columns].astype(str).sum(1).isin(df1.astype(str).sum(1))]

【讨论】:

  • 如果 dtypes 不同,这将失败,所以在 OP 中 df1.loc[0,'col1'].astype(str)'500'df2.loc[0,'col1'].astype(str)'500.0'isin 不匹配
  • 对于这个特定的情况,这是可行的:df2[~df2[df1.columns].astype(str).sum(1).isin(df1.astype(np.float).astype(str).sum(1))]
  • @Dan 感谢您的建议。但是,如果 df1 的列比我们想要比较的列多,这也可以吗?如果一个或任何一列中的值是字符串,这仍然有效吗?所以我们将比较浮点数/整数和字符串的混合
  • 将 df2 中的值的元组提取到列表中,然后将其与 df1 中相关列的值进行比较是否是一种解决方案?理想情况下,尽管我们应该能够在 pandas 中完全做到这一点
  • @RedSparrow nope isin 是 pandas 的函数
猜你喜欢
  • 2021-09-07
  • 1970-01-01
  • 2021-03-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-29
  • 2021-11-15
  • 2020-09-03
相关资源
最近更新 更多