pandas:包含用于分隔行的列表的记录

时间:2018-04-19 14:05:07

标签: python pandas numpy dataframe split

我有像这样的Python Pandas DataFrame(NCBI RefSeq的UCSC架构):

chrom   exonStart     exonEnds      name
chr1    100,200,300   110,210,310   gen1
chr1    500,700       600,800       gen2
chr2    50,60,70,80   55,65,75,85   gen3

我希望将exonStarts和exonEnds中的值配对,并将它们作为单独的行放置(保留其余的相应信息):

chrom   exonStart     exonEnds      name
chr1    100           110           gen1
chr1    200           210           gen1
chr1    300           310           gen1
chr1    500           600           gen2
chr1    700           800           gen2
chr2    50            55            gen3
chr2    60            65            gen3
chr2    70            75            gen3
chr2    80            85            gen3

我正在考虑使用python / pandas函数的组合:

  拉链,分裂,融化,连续

但不知怎的,它对我不起作用

3 个答案:

答案 0 :(得分:3)

在理解中使用zipsplit

pd.DataFrame([
    [c, s, e, n]
    for c, S, E, n in df.itertuples(index=False)
    for s, e in zip(S.split(','), E.split(','))
], columns=df.columns)

  chrom exonStart exonEnds  name
0  chr1       100      110  gen1
1  chr1       200      210  gen1
2  chr1       300      310  gen1
3  chr1       500      600  gen2
4  chr1       700      800  gen2
5  chr2        50       55  gen3
6  chr2        60       65  gen3
7  chr2        70       75  gen3
8  chr2        80       85  gen3

答案 1 :(得分:2)

这是使用numpyintertools.chain的一种方式。

我们的想法是首先将逗号分隔的字段拆分为列表。然后构造结果数据框,重复或链接值是必要的。

import numpy as np
from itertools import chain

df['exonStart'] = df['exonStart'].str.split(',')
df['exonEnds'] = df['exonEnds'].str.split(',')

lens = list(map(len, df['exonStart']))

res = pd.DataFrame({'chrom': np.repeat(df['chrom'], lens),
                    'exonStart': list(chain.from_iterable(df['exonStart'])),
                    'exonEnds': list(chain.from_iterable(df['exonEnds'])),
                    'name': np.repeat(df['name'], lens)})

print(res)

#   chrom exonEnds exonStart  name
# 0  chr1      110       100  gen1
# 0  chr1      210       200  gen1
# 0  chr1      310       300  gen1
# 1  chr1      600       500  gen2
# 1  chr1      800       700  gen2
# 2  chr2       55        50  gen3
# 2  chr2       65        60  gen3
# 2  chr2       75        70  gen3
# 2  chr2       85        80  gen3

请注意,您可能希望在此过程结束时将数字列转换为int

答案 2 :(得分:1)

我使用unstackstack

来解决这个问题
df.set_index(['chrom','name']).apply(lambda x : x.str.split(','),1).\
   stack().apply(pd.Series).stack().unstack(-2).\
       reset_index().drop('level_2',1)
Out[1201]: 
  chrom  name exonStart exonEnds
0  chr1  gen1       100      110
1  chr1  gen1       200      210
2  chr1  gen1       300      310
3  chr1  gen2       500      600
4  chr1  gen2       700      800
5  chr2  gen3        50       55
6  chr2  gen3        60       65
7  chr2  gen3        70       75
8  chr2  gen3        80       85