【问题标题】:Using pandas, find the intersecting regions between two DataFrames?使用 pandas,找到两个 DataFrame 之间的相交区域?
【发布时间】:2019-11-27 18:48:07
【问题描述】:

我有两个 pandas 数据框,使用 python3.x:

import pandas as pd

dict1 = {0:['chr1','chr1','chr1','chr1','chr2'], 
    1:[1, 100, 150, 900, 1], 2:[100, 200, 500, 950, 100], 
    3:['feature1', 'feature2', 'feature3', 'feature4', 'feature4'], 
    4:[0, 0, 0, 0, 0], 5:['+','+','-','+','+']}

df1 = pd.DataFrame(dict1)

print(df1)

##       0    1    2         3  4  5
## 0  chr1    1  100  feature1  0  +
## 1  chr1  100  200  feature2  0  +
## 2  chr1  150  500  feature3  0  -
## 3  chr1  900  950  feature4  0  +
## 4  chr2    1  100  feature4  0  +

dict2 = {0:['chr1','chr1'], 1:[155, 800], 2:[200, 901], 
    3:['feature5', 'feature6'], 4:[0, 0], 5:['-','+']}

df2 = pd.DataFrame(dict2)
print(df2)
##       0    1    2         3  4  5
## 0  chr1  155  200  feature5  0  -
## 1  chr1  800  901  feature6  0  +

这些数据框中要关注的列是前三列:位置、开始和结束。每个 start:end 值表示位置上的距离(例如chr1chr2chr3)。

我想输出df1df2 的交集。这是正确的输出:

chr1    155 200 feature2    0   +
chr1    155 200 feature3    0   -
chr1    900 901 feature4    0   +

解释:我们找到df1df2 的交集。所以,feature2feature3 在 155 到 200 处相交 df2feature4 在 900 到 901 处重叠 df2

什么是最有效的(就运行时间和 RAM 而言)找到交叉点?

编辑:这里有一个类似的 Python 包:https://daler.github.io/pybedtools/intersections.html

【问题讨论】:

  • 您想返回第一个 GFF 中与第二个 GFF 中的特征重叠的特征,并将位置子集仅包含在您的第二个 GFF 中?
  • @CJR 是的,没错。目前,我脑海中的第一个“小步骤”是忽略这些特征,并确保我的重叠间隔正确。
  • 所以如果其中一个。 df2.start == df1.start 或 b。 df2.end == df2.end,你应该保留那行吗?在这种情况下,还不清楚什么位置、开始和结束。我认为为简单起见,您应该通过数据框中的列名来引用这些列。
  • @LiamShalon 是的,但请注意这不是我保留的行——它是重叠的位置。 chr1 900 901 feature4 0 + 不是现有行(这可能很清楚)
  • @EB2127 我不清楚是什么构成了应包含在您的交叉点数据框中的内容

标签: python python-3.x pandas dataframe merge


【解决方案1】:
import pandas as pd

df1 = pd.DataFrame({0:['chr1','chr1','chr1','chr1','chr2'],
    1:[1, 100, 150, 900, 1], 2:[100, 200, 500, 950, 100],
    3:['feature1', 'feature2', 'feature3', 'feature4', 'feature4'],
    4:[0, 0, 0, 0, 0], 5:['+','+','-','+','+']})

df2 = pd.DataFrame({0:['chr1','chr1'], 1:[155, 800], 2:[200, 901],
    3:['feature5', 'feature6'], 4:[0, 0], 5:['-','+']})

您可以使用apply 和一些逻辑测试来查找重叠。不过,您必须遍历染色体组。您应该能够执行类似的操作来查找和修复需要调整的开始和停止。以后有时间我会写点东西的。

new_dfs = []

for chr_name, chr_df in df1.groupby(0):
    chr_df2 = df2.loc[df2[0] == chr_name]
    overlapping = (chr_df[1].apply(lambda x: chr_df2[2] >= x) & chr_df[2].apply(lambda x: chr_df2[1] <= x)).any(axis=1)
    new_dfs.append(chr_df.loc[overlapping, :])

new_dfs = pd.concat(new_dfs)

总体而言,这将节省内存,但不会超快。如果你想要快速,你可能不得不编写一些复杂的索引。

【讨论】:

  • 我注意到这并不能给出正确的答案。它输出1 chr1 100 200 feature2 0 + 2 chr1 150 500 feature3 0 - 3 chr1 900 950 feature4 0 +
  • 是的,这只会发现重叠。下一部分要困难得多,因为有大量的边缘条件(如果 A 中的一个特征与 B 中的 2 个特征重叠,你该怎么办,等等)。
  • 这是比上述方法更好的解决方案。交叉点 = pd.merge(df1[[0, 1, 2, 4, 5]], df2[[0, 1, 2, 4, 5]], how='inner')
  • 如果只做inner join,在feature start和stop不一样,feature名字不一样的情况下效果如何?
猜你喜欢
  • 2020-06-14
  • 2021-07-31
  • 1970-01-01
  • 2019-11-11
  • 1970-01-01
  • 2013-08-07
  • 1970-01-01
  • 1970-01-01
  • 2018-03-11
相关资源
最近更新 更多