基于另一个DataFrame的范围筛选Pandas DataFrame行
没问题,我来帮你搞定基于另一个DataFrame的范围条件筛选df_json的需求~ 先给你梳理几种实用的方法,你可以根据自己的数据集大小和具体需求来选:
首先,先把你的df_json用代码复现出来,方便后续测试:
import pandas as pd # 构建你的df_json data_json = { 'chromosome': ['7', '12', '17', '6', '9'], 'ensembl_id': ['ENSG00000122543', 'ENSG00000111325', 'ENSG00000181396', 'ENSG00000119900', 'ENSG00000106809'], 'gene_end': [5886362, 122980043, 82418637, 71308950, 92404696], 'gene_start': [5879827, 122974580, 82389223, 71288803, 92383967] } df_json = pd.DataFrame(data_json)
假设我们用来筛选的另一个DataFrame叫df_filter,结构大概是包含染色体、筛选起始位、筛选结束位,我先给个示例:
# 示例筛选条件DataFrame,你替换成自己的实际数据即可 data_filter = { 'chromosome': ['7', '17'], 'filter_start': [5870000, 82390000], 'filter_end': [5890000, 82420000] } df_filter = pd.DataFrame(data_filter)
方法1:合并后筛选(适合小数据集,逻辑直观)
先把两个DataFrame按染色体关联,再用区间重叠的条件筛选,最后保留原df_json的列:
# 按染色体合并两个表 merged_df = pd.merge(df_json, df_filter, on='chromosome', how='inner') # 核心:判断基因区间和筛选区间是否重叠(通用重叠逻辑) # 如果你的需求是基因完全落在筛选区间内,把条件改成: # (merged_df['gene_start'] >= merged_df['filter_start']) & (merged_df['gene_end'] <= merged_df['filter_end']) filtered_df = merged_df[(merged_df['gene_start'] <= merged_df['filter_end']) & (merged_df['gene_end'] >= merged_df['filter_start'])] # 去除筛选条件列,保留原数据结构并去重 filtered_df = filtered_df[df_json.columns].drop_duplicates()
方法2:逐行判断(适合需要自定义复杂逻辑的场景)
如果你的筛选逻辑比较特殊,可以用apply逐行检查每一条基因是否符合筛选条件:
def check_match(row, filter_df): # 先找到同染色体的筛选条件 same_chrom_filters = filter_df[filter_df['chromosome'] == row['chromosome']] if same_chrom_filters.empty: return False # 检查是否有重叠的区间 return any((row['gene_start'] <= same_chrom_filters['filter_end']) & (row['gene_end'] >= same_chrom_filters['filter_start'])) # 应用函数筛选符合条件的行 filtered_df = df_json[df_json.apply(check_match, filter_df=df_filter, axis=1)]
方法3:Interval索引优化(适合大数据集,效率更高)
如果你的数据量很大,上面两种方法速度不够,可以用pandas的IntervalIndex来优化区间判断:
# 按染色体分组,为每个染色体创建筛选区间的索引 filter_intervals = df_filter.groupby('chromosome').apply( lambda x: pd.IntervalIndex.from_arrays(x['filter_start'], x['filter_end'], closed='both') ) def check_interval_overlap(row): chrom = row['chromosome'] if chrom not in filter_intervals: return False # 生成当前基因的区间,检查是否和筛选区间有重叠 gene_interval = pd.Interval(row['gene_start'], row['gene_end'], closed='both') return any(gene_interval.overlaps(interval) for interval in filter_intervals[chrom]) filtered_df = df_json[df_json.apply(check_interval_overlap, axis=1)]
用上面的示例筛选条件,最终筛选出来的结果是:
| chromosome | ensembl_id | gene_end | gene_start |
|---|---|---|---|
| 7 | ENSG00000122543 | 5886362 | 5879827 |
| 17 | ENSG00000181396 | 82418637 | 82389223 |
内容的提问来源于stack exchange,提问作者Radha Krishna
相关产品推荐
相关产品推荐

