【问题标题】:take a subset of a pandas data frame based on the column names根据列名获取熊猫数据框的子集
【发布时间】:2013-04-14 03:28:59
【问题描述】:

我有一个包含 140 个样本(列)和约 27000 个 SNP(行)的 pd.DataFrame。每个列名都有一个群体名称和一个数字(例如 'FLFL04' 或 'MI03' ),其中包含 6 个不同的群体和群体中不同数量的样本。

我想根据种群名称提取各个种群的子集以进行进一步计算(Hardy-Weinberg 精确检验);我可以用循环和正则表达式来做到这一点,但希望有一个更快的解决方案。 有没有办法根据列名(而不是它们的内容)创建子集?

编辑: 我目前的方法如下:

(任何 pd.DataFrame 都可以,具有以下列:

data.columns = ['FLFL04', 'FLFL08', 'FLFL08replicate', 'FLFL10', 'FLFL13', 'FLFL14', 'FLFL15', 'FLFL15replicate', 'FLFL16', 'FLFL17', 'FLFL17replicate', 'FLFL19', 'FLFL20', 'FLFL20replicate', 'FLFL21', 'FLFL23', 'FLFL26', 'FLFL28', 'FLFL28replicate', 'FLFL29', 'FLFL29replicate', 'FLFL30', 'HSPQ01', 'HSPQ01replicate', 'HSPQ01replicate2', 'HSPQ02', 'HSPQ02replicate', 'HSPQ02replicate2', 'HSPQ03', 'HSPQ04', 'HSPQ04replicate', 'HSPQ04replicate2', 'HSPQ06', 'HSPQ07', 'HSPQ08', 'HSPQ09', 'HSPQ09replicate', 'HSPQ10', 'HSPQ10replicate', 'HSPQ11', 'HSPQ12', 'HSPQ13', 'HSPQ14', 'HSPQ15', 'HSPQ16', 'HSPQ17', 'HSPQ18', 'HSPQ19', 'HSPQ21', 'HSPQ22', 'HSPQ22replicate', 'KFO1', 'KFO2', 'KFO3', 'KFO4', 'KFO5', 'KFO8', 'MI01', 'MI02', 'MI03', 'MI03replicate', 'MI03replicate2', 'MI04', 'MI05', 'MI06', 'MI06replicate', 'MI06replicate2', 'MI08', 'MI09', 'MI09replicate', 'MI09replicate2', 'MI10', 'MI11', 'MI12', 'MI12replicate', 'MI13', 'MI13replicate', 'MI14', 'MI15', 'MI16', 'MI16replicate', 'MI17', 'MI18', 'MI19', 'MI20', 'MI21', 'SFQ01', 'SFQ02', 'SFQ03', 'SFQ03replicate', 'SFQ05', 'SFQ05replicate', 'SFQ06', 'SFQ06replicate', 'SFQ07', 'SFQ08', 'SFQ08replicate', 'SFQ09', 'SFQ09replicate', 'SFQ10', 'SFQ10replicate', 'SFQ11', 'SFQ13', 'SFQ14', 'SFQ15', 'SFQ16', 'SFQ17', 'SFQ21', 'SFQ23', 'SFQ24', 'SFQ25', 'SFQ26', 'WWA01', 'WWA01replicate', 'WWA01replicate2', 'WWA03', 'WWA03replicate', 'WWA03replicate2', 'WWA04', 'WWA05', 'WWA05replicate', 'WWA05replicate2', 'WWA07', 'WWA08', 'WWA08replicate', 'WWA09', 'WWA10', 'WWA12', 'WWA17', 'WWA17replicate', 'WWA18', 'WWA21', 'WWA23', 'WWA24', 'WWA25', 'WWA25replicate', 'WWA26', 'WWA27', 'WWA28', 'WWA30']

def get_pop_subset(pop_list, pop_name): 
    pop_result_list = []
    for i, pop in enumerate(data.columns):
    curr_pop = re.findall('([A-Z]+)', pop)[0]
    if curr_pop == pop_name:
        pop_result_list.append(pop)
    return pop_result_list

pops = ['FLFL', 'HSPQ', 'KFO', 'MI', 'SFQ', 'WWA']
subsets = []
for val in pops:
    subsets.append(get_pop_subset(data.columns, val))

for val in subsets:
    print data[val]

然后我调用其他函数而不是

    print data[val]

并将每个附加到一个新的df。 虽然这可行,但我希望获得更快且可能更有效的解决方案

谢谢, 马丁

【问题讨论】:

  • 带有一些列的示例 DataFrame 会很有用。基于有限的信息,正则表达式和 for 循环可能不是一个糟糕的方法。你试过什么。
  • 您可能已经在“正则表达式和循环”语句中提到了这一点,但您可以像这样创建子集数据框,df.ix[:,"FLFL01":"FLFL20"]。或者您可以遍历 df.columns 并获取您想要子集的列名列表并使用它进行切片,df.ix[:,name_list]
  • 根据我想要的剪辑的复杂程度,我经常使用 listcomp,比如df[[col for col in df.columns if some_complex_condition(col)]]。但是,根据您对子集的含义,您实际上可能在转置后在groupby 组之后。查看您想要获得的输出类型肯定会有所帮助。

标签: python regex pandas


【解决方案1】:

使用正则表达式获取列名的任何子字符串,以“FLFL”开头后跟两位数字,删除所有不匹配项 (NA),删除重复项并排序。

df.columns.str.extract(r'(FLFL\d\d)', expand=False).dropna().drop_duplicates().sort_values()

【讨论】:

  • 不,这并没有真正做到(除了晚了大约 8 年 :) 那时,我对所有流行音乐都不感兴趣,而不仅仅是 FLFL
  • 人们和我一样,通过谷歌搜索登陆这里,希望得到答案。只是想帮助别人。
【解决方案2】:

您不能使用带有参数“regex”的内置 DataFrame 方法“filter”来实现相同的目标吗?例如,

df2 = df.filter(regex='FLFL')

返回一个新的 DataFrame,所有列都以 FLFL 开头。

【讨论】:

  • 不是真的,因为我对所有流行音乐都感兴趣,而不仅仅是 FLFL。还是谢谢
【解决方案3】:

好的,对于你的情况,我会使用groupby。您可以使用 axis=1 将函数传递给它以遍历列(请参阅文档中的 here):

>>> df 
   FLFL04  FLFL29rep  HSPQ12  MI03repl  MI16repl  SFQ10re  WWA05r
0       0          3       6         9        12       15      18
1       1          4       7        10        13       16      19
2       2          5       8        11        14       17      20
>>> df.groupby(lambda x: re.match("[A-Z]+", x).group(), axis=1)
<pandas.core.groupby.DataFrameGroupBy object at 0x9ae660c>
>>> grouped = df.groupby(lambda x: re.match("[A-Z]+", x).group(), axis=1)

然后我们可以遍历这些组:

>>> for name, group in grouped:
    print 'group name:', name
    print 'dataframe:'
    print group
...     
group name: FLFL
dataframe:
   FLFL04  FLFL29rep
0       0          3
1       1          4
2       2          5
group name: HSPQ
dataframe:
   HSPQ12
0       6
1       7
2       8
group name: MI
dataframe:
   MI03repl  MI16repl
0         9        12
1        10        13
2        11        14
group name: SFQ
dataframe:
   SFQ10re
0       15
1       16
2       17
group name: WWA
dataframe:
   WWA05r
0      18
1      19
2      20

或者把它变成字典:

>>> pprint.pprint(dict(list(grouped)))
{'FLFL':    FLFL04  FLFL29rep
0       0          3
1       1          4
2       2          5,
 'HSPQ':    HSPQ12
0       6
1       7
2       8,
 'MI':    MI03repl  MI16repl
0         9        12
1        10        13
2        11        14,
 'SFQ':    SFQ10re
0       15
1       16
2       17,
 'WWA':    WWA05r
0      18
1      19
2      20}

【讨论】:

  • 嗬嗬,这看起来很甜蜜!谢谢@DSM。有另一项可能需要一段时间的工作正在运行,但迫不及待地想测试一下! (再次提醒我不要回避groupby
  • 效果很好!但是,我不能循环组(分组),因为“'builtin_function_or_method'对象不可迭代”。
  • @schimar:你忘了match 中的最后一个() 吗?这是group(),而不是.group。如果没有,请让我知道完整的回溯,这可能是一个简单的错字。
  • 我复制了你的groupby 声明,所以不,括号在那里。 for group in grouped: 然后进一步循环:for i, locus in enumerate(group): 但不让我这样做
  • 如果你使用for group in grouped:,那应该可以工作,尽管group 将是一个二元组,其中第一个元素是名称,第二个元素是数据框。 (你会注意到我使用了for name, group in grouped:。)
猜你喜欢
  • 2016-11-29
  • 2022-11-18
  • 2021-02-03
  • 2016-03-28
  • 1970-01-01
  • 2015-05-10
  • 1970-01-01
  • 2020-06-13
  • 1970-01-01
相关资源
最近更新 更多