向行添加值列表,然后将数据帧转换为长格式

2024-05-13 00:11:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个数据框,索引是基因组位置,值是p值:

import pandas as pd
from StringIO import StringIO
from collections import defaultdict

data = """Pos   MedialIIvsD  LateralIIvsD  MedialP02IIvsD  MedialP09IIvsD
chr1_-_12200      0.557431      0.066554        0.738343        0.029935
chr1_-_12600      0.737887      0.069167        0.829568        0.409495
chr1_-_48400      0.349833      0.600912        0.964103        0.765195
chr1_-_172800     0.729035      0.035198        0.866111        0.385711"""

df = pd.read_csv(StringIO(data), sep='\s+', index_col=False, 
                 header=False)

此外,我还有一个dict,可以将不同的基因组位置映射到不同的基因:

pos_to_gene = defaultdict(list, {"chr1_-_12200": ["GENE1"],
                                 "chr1_-_12600": ["GENE1", "GENE2"],
                                 "chr1_-_172800": ["GENE3"]})

我想要实现的是在这个数据帧中添加Gene作为列。这对我来说并不简单,因为在一个基因组位置可以有几个基因:

pd.Series(df.index.values).apply(lambda pos: pos_to_gene[pos])
0           [GENE1]
1    [GENE1, GENE2]
2                []
3           [GENE3]
dtype: object

如何以这样的长格式实现输出数据帧?你知道吗

Gene   Pos   MedialIIvsD  LateralIIvsD  MedialP02IIvsD  MedialP09IIvsD
GENE1  chr1_-_12200      0.557431      0.066554        0.738343        0.029935
GENE1  chr1_-_12600      0.737887      0.069167        0.829568        0.409495
GENE2  chr1_-_12600      0.737887      0.069167        0.829568        0.409495
NaN    chr1_-_48400      0.349833      0.600912        0.964103        0.765195
GENE3  chr1_-_172800     0.729035      0.035198        0.866111        0.385711

Tags: 数据fromposimport基因组datapdchr1
2条回答

这里有个窍门pd系列(1,索引=…)并让熊猫对齐:

In [11]: s = df["Pos"].apply(lambda x: pd.Series(1, pos_to_gene[x])).stack(0)

In [12]: s
Out[12]:
0  GENE1    1
1  GENE1    1
   GENE2    1
3  GENE3    1
dtype: float64

您可以重置索引,然后简单地加入:

In [13]: s.index.names = [None, "Gene"]

In [14]: gene = s.reset_index("Gene")[["Gene"]]

In [15]: gene
Out[15]:
    Gene
0  GENE1
1  GENE1
1  GENE2
3  GENE3

In [16]: gene.join(df)
Out[16]:
    Gene            Pos  MedialIIvsD  LateralIIvsD  MedialP02IIvsD  MedialP09IIvsD
0  GENE1   chr1_-_12200     0.557431      0.066554        0.738343        0.029935
1  GENE1   chr1_-_12600     0.737887      0.069167        0.829568        0.409495
1  GENE2   chr1_-_12600     0.737887      0.069167        0.829568        0.409495
3  GENE3  chr1_-_172800     0.729035      0.035198        0.866111        0.385711

如果要包含NaN行(答案中没有),那么outer join:

In [17]: gene.join(df, how="outer")
Out[17]:
    Gene            Pos  MedialIIvsD  LateralIIvsD  MedialP02IIvsD  MedialP09IIvsD
0  GENE1   chr1_-_12200     0.557431      0.066554        0.738343        0.029935
1  GENE1   chr1_-_12600     0.737887      0.069167        0.829568        0.409495
1  GENE2   chr1_-_12600     0.737887      0.069167        0.829568        0.409495
2    NaN   chr1_-_48400     0.349833      0.600912        0.964103        0.765195
3  GENE3  chr1_-_172800     0.729035      0.035198        0.866111        0.385711

或者,您可以在纯python中创建gene(而不是使用apply):

inds, gens = [], []
for i, p in df["Pos"].iteritems():
    for g in pos_to_gene[p]:
        inds.append(i)
        gens.append(g)
gene = pd.Series(gens, inds)

运用我在answer here中学到的知识:

df.insert(0, "Gene", df.Pos.apply(lambda pos: pos_to_gene[pos]))

def expand(row):
    genes = row['Gene']
    s = pd.Series(row['Pos'], index=list(set(genes)))
    return s

sdf = df.apply(expand, axis=1).stack()

退货

0  GENE1     chr1_-_12200
1  GENE1     chr1_-_12600
   GENE2     chr1_-_12600
3  GENE3    chr1_-_172800
dtype: object

非常接近;只缺少其余的数据。你知道吗

现在剩下的就是合并堆叠的数据帧(sdf)和原始数据帧(df)。你知道吗

sdf = sdf.to_frame().reset_index(level=1, drop=False)
sdf.columns = ["Gene", "Pos"]
pd.merge(sdf, df, left_on = 'Pos', right_on = 'Pos')

就这样!你知道吗

    Gene            Pos  MedialIIvsD  LateralIIvsD  MedialP02IIvsD  \
0  GENE1   chr1_-_12200     0.557431      0.066554        0.738343
1  GENE1   chr1_-_12600     0.737887      0.069167        0.829568
2  GENE2   chr1_-_12600     0.737887      0.069167        0.829568
3  GENE3  chr1_-_172800     0.729035      0.035198        0.866111

   MedialP09IIvsD
0        0.029935
1        0.409495
2        0.409495
3        0.385711

也许有更聪明的方法可以做到这一点。你知道吗

相关问题 更多 >