基于字符串集从Pandas行中提取键值对数据
从Pandas含分号分隔键值对的列中提取特定数据的解决方案
我来帮你解决这个问题,结合你给出的类似GTF格式的列数据,这里有几种实用的方案,直接就能套用:
1. 先模拟你的数据场景
首先我们先构造和你示例一致的DataFrame,方便后续演示:
import pandas as pd # 模拟你的输入数据 data = { 'chromosome': [114188457, 114188457], 'info': [ 'gene_id "ENSMUSG00000111734"; gene_version "1"; transcript_id "ENSMUST00000214237"; transcript_version "1"; exon_number "23"; gene_name "Gm29825"; gene_source "havana"; gene_biotype "lincRNA"', 'gene_id "ENSMUSG00000090012"; gene_version "2"; transcript_id "ENSMUST00000150001"; transcript_version "1"; exon_number "1"; gene_name "Actb"; gene_source "havana"; gene_biotype "protein_coding"' ] } df = pd.DataFrame(data)
2. 提取单个特定键(比如gene_id)
如果只需要提取某一个键的值,用str.extract结合正则表达式是最高效的方式,直接匹配键对应的双引号内的值:
# 提取gene_id,正则捕获双引号中的内容 df['gene_id'] = df['info'].str.extract(r'gene_id "([^"]+)"') # 查看结果 print(df[['chromosome', 'gene_id']])
解释:正则gene_id "([^"]+)"会精准匹配gene_id "开头的片段,然后捕获双引号之间的所有非引号字符,完美提取出目标值。
3. 批量提取多个键(比如gene_id、gene_name、exon_number)
如果需要同时提取多个键,写一个自定义函数把字符串转成字典,再按需提取会更灵活:
def extract_target_info(info_str, target_keys): # 处理空值情况 if pd.isna(info_str): return {key: pd.NA for key in target_keys} # 按分号分割所有键值对,清理掉空的片段 kv_pairs = [pair.strip() for pair in info_str.split(';') if pair.strip()] # 把键值对转成字典,去掉值的双引号 info_dict = {} for pair in kv_pairs: # 按第一个空格分割(避免值里包含空格的情况) key, value = pair.split(' ', 1) info_dict[key] = value.strip('"') # 返回需要的键对应的值,没有则返回NA return {key: info_dict.get(key, pd.NA) for key in target_keys} # 指定要提取的键列表 target_keys = ['gene_id', 'gene_name', 'exon_number'] # 应用函数并合并到原DataFrame extracted_df = df['info'].apply(lambda x: pd.Series(extract_target_info(x, target_keys))) df = pd.concat([df, extracted_df], axis=1) # 查看结果 print(df[['chromosome', 'gene_id', 'gene_name', 'exon_number']])
一些实用的注意事项
- 如果键和值之间是多个空格,可以把
split(' ', 1)改成split(r'\s+', 1),用正则匹配任意数量的空格。 - 对于超大规模数据集,单个键提取优先用
str.extract,速度比apply函数快很多;多键提取如果追求性能,可以用str.extractall结合分组转置的方式。 - 如果你的数据中值没有双引号,只需要去掉
strip('"')这一步即可。
内容的提问来源于stack exchange,提问作者Siddharth
相关产品推荐
相关产品推荐

