我有一个数据框(600k 行)
index chr position other_cols
1 1 100 ...
2 1 2100
3 1 3300
4 2 4
5 2 2200
6 3 8420
我有另一个数据框 df2(120 万行):
index chr start stop
1 1 1 100
2 1 2000 3000
3 1 4000 8000
4 2 1 1500
5 3 20 40000
我希望我的最终数据框通过查找位于某个区域内的位置来基本上将 df1 映射到 df2。 :
index chr position matched_start matched_end other_cols (from df1)
1 1 100 1 100 ...
2 1 2100 2000 3000
3 2 4 1 1500
4 3 8420 20 40000
这是我尝试运行的代码,但每次我尝试在整个 dfs 上运行时,我的笔记本电脑都会崩溃(仅当我使用小子集时才有效)。我也尝试过分块进行,但它也导致我的笔记本电脑崩溃。
# Merge the DataFrames based on the 'chromosome' column
merged_df = pd.merge(df1, df2, on='chr', how='inner')
# Filter the rows where variant_position lies within the start/end ranges
filtered_df = merged_df[(merged_df['position'] >= merged_df['start']) & (merged_df['position'] <= merged_df['end'])]
我假设每个唯一的
chr
没有任何重叠的间隔(并假设df2
按起始位置排序):
x = df2.groupby('chr')[['start', 'stop']].agg(list)
all_dfs = []
for ch, g in df1.groupby('chr'):
start_arr, stop_arr = np.array(x.loc[ch, 'start']), np.array(x.loc[ch, 'stop'])
idx = np.searchsorted(start_arr, g['position']) - 1
g.loc[:, ['matched_start', 'matched_end']] = np.array([start_arr[idx], stop_arr[idx]]).T
all_dfs.append(g[g['position'] <= stop_arr[idx]])
df = pd.concat(all_dfs)
print(df)
打印:
index chr position other_col matched_start matched_end
0 1 1 100 1 1 100
1 2 1 2100 2 2000 3000
3 4 2 4 4 1 1500
5 6 3 8420 6 20 40000
初始
df1
:
index chr position other_col
0 1 1 100 1
1 2 1 2100 2
2 3 1 8300 3
3 4 2 4 4
4 5 2 2200 5
5 6 3 8420 6
初始
df2
:
index chr start stop
0 1 1 1 100
1 2 1 2000 3000
2 3 1 4000 8000
3 4 2 1 1500
4 5 3 20 40000
注意:我做了一些粗略的基准测试,在 600k/1.2M 长度的数据帧上执行此操作花了我不到 2 分钟的时间 (5700x/Python 3.10)