python - 根据 pandas 中的其他数据帧过滤一个数据帧

标签 python pandas dataframe

我在 pandas 中有两个 DataFrame:

import pandas as pd

df1 = pd.DataFrame({'Name': ["A", "B", "C", "C","D","D","E"],
                   'start': [50, 124, 1, 159, 12, 26,110],
                   'stop': [60, 200, 19, 200, 24, 30,160]})
df2 = pd.DataFrame({'Name': ["B", "C","D","E"],
                   'start': [126, 143, 19, 159],
                   'stop': [129, 220, 27, 200]})

print(df1)

  Name  start  stop
0    A     50    60
1    B    124   200
2    C      1    19
3    C    159   200
4    D     12    24
5    D     26    30
6    E    110   160

print(df2)

  Name  start  stop
0    B    126   129
1    C    143   220
2    D     19    27
3    E    159   200

我想使用以下条件过滤 df1 以删除基于 df2 的行:

  1. 名称应同时出现在 df1 和 df2 中
  2. 名称从开始到停止的范围与其他 DataFrame 中该名称从开始到停止的范围重叠

这将给出:

  Name  start  stop
0    B    124   200
1    C    159   200
2    D     12    24
3    D     26    30
4    E    110   160

地点:

  • A 已被删除,因为 df2 中没有 A
  • B 被保留,因为 df2 中 B 的起点和终点嵌套在 df1 中 B 的起点和终点
  • df1 的一个 C 已被删除,因为它的值与 df2 不重叠,而另一个则被保留,因为它嵌套在 df2 中 C 的开始和停止范围内
  • 两个 D 都被保留,因为它们都与 df2 中 D 的范围重叠
  • E 被保留,因为它的范围与 df2 中的 E 重叠

任何帮助将不胜感激!

最佳答案

为了解决您的问题,我应用了一种类似于 SQL 的方式来模仿以下查询:

SELECT
  df.Name, df.start_x AS start, df.stop_x AS stop
FROM (
  SELECT
    df1.Name, df1.start AS start_x, df1.stop AS stop_x,
              df2.start AS start_y, df2.stop AS stop_y
    FROM df1
    INNER JOIN df2
      ON df1.Name = df2.Name
) AS df
WHERE (df.stop_y >= df.start_x) AND (df.stop_x >= df.start_y)

此查询已转换为以下使用 pandas.merge 的代码片段方法。请注意,您必须在表达式 (df.stop_y> = df.start_x) & (df.stop_x> = df.start_y) 中使用括号。没有它们,代码会抛出异常

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

import pandas as pd

df1 = pd.DataFrame({'Name': ["A", "B", "C", "C","D","D","E"],
                   'start': [50, 124, 1, 159, 12, 26,110],
                   'stop': [60, 200, 19, 200, 24, 30,160]})
df2 = pd.DataFrame({'Name': ["B", "C","D","E"],
                   'start': [126, 143, 19, 159],
                   'stop': [129, 220, 27, 200]})
df = pd.merge(df1, df2, on=['Name'])
df = df[(df.stop_y >= df.start_x) & (df.stop_x >= df.start_y)]
df.rename(columns={'start_x':'start', 'stop_x':'stop'}, inplace=True)
df.drop(['start_y', 'stop_y'], axis=1, inplace=True)
df.reset_index(drop=True, inplace=True)
print(df)

输出:

  Name  start  stop
0    B    124   200
1    C    159   200
2    D     12    24
3    D     26    30
4    E    110   160

演示 Repl.it .

关于python - 根据 pandas 中的其他数据帧过滤一个数据帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58741434/

相关文章:

Python 3 : perform additional calculation inside a generator

python - 在 pandas 中添加时间戳偏移量

python - 获取所选值的索引

python - 使用 apply、transform、agg - Python Pandas 时如何引用 groupby 索引?

python - 将 Excel 格式化为 DataFrame

python - 比较数据框中的 2 个连续单元格

python - 如何让pyflakes忽略一些错误?

python - Anaconda 和 Brew 的最佳实践

python - 使用 Python 的 3 个矩阵的 Kronecker 乘积

python - Pandas 适用,但仅适用于满足条件的行