0

我有一个熊猫数据框,我想根据另外两列创建一个新列。数据框如下所示:

REF ALT 30_10
A   G   0:0
G   A   .:.
G   A   .:.
A   G   .:.
T   C   .:.
A   G   1:1
G   A   0:0
C   T   1:1
C   T   0:0
T   A   0:0
T   G   0:0
G   A   0:0
C   T   0:1

我想要一个基于 REF ALT 和 30_10 的新专栏。新列将通过将 30_10 列与 REF 和 ALT 列进行比较来表示,其中 30_10 列中的 0 表示 REF,30_10 中的 1 表示 ALT,而 . 表示 0。新列应如下所示:

REF ALT 30_10 new_column
A   G   0:0  A:A
G   A   .:.  0:0
G   A   .:.  0:0
A   G   .:.  0:0
T   C   .:.  0:0 
A   G   1:1  G:G
G   A   0:0  G:G
C   T   1:1  T:T
C   T   0:0  C:C
T   A   0:0  T:T
T   G   0:0  T:T
G   A   0:0  G:G
C   T   0:1  C:T

只是想知道是否有一种快速的pandasnumpy方法可以做到这一点?我似乎找不到我需要的东西。

谢谢!

4

2 回答 2

1

我注意到您可以分别通过索引 0 和 1 访问REFALT列,但这不适用于点“.”。但是如果我们在位置添加一个带有零的临时列2

>>> df.insert(loc=2, column='tmp', value='0')
>>> df
  REF ALT tmp 30_10
0   A   G   0   0:0
1   G   A   0   .:.
2   G   A   0   .:.
3   A   G   0   .:.
4   T   C   0   .:.

并替换“。” ,2我们基本上可以在所有三种情况下使用索引,即,我们可以

  • 在 ':' 处拆分以获取索引xy,
  • 获取第 x/y 列的内容,
  • 并重新加入。
>>> df['new_column'] = df.apply(lambda row:':'.join(row.iloc[int(i)] for i in row['30_10'].replace('.', '2').split(':')), axis=1)
>>> df = df.drop('tmp', axis=1) # drop the temporary column
>>> df
   REF ALT tmp 30_10 new_column
0    A   G   0   0:0        A:A
1    G   A   0   .:.        0:0
2    G   A   0   .:.        0:0
3    A   G   0   .:.        0:0
4    T   C   0   .:.        0:0
5    A   G   0   1:1        G:G
6    G   A   0   0:0        G:G
7    C   T   0   1:1        T:T
8    C   T   0   0:0        C:C
9    T   A   0   0:0        T:T
10   T   G   0   0:0        T:T
11   G   A   0   0:0        G:G
12   C   T   0   0:1        C:T
于 2021-08-04T20:27:09.530 回答
1

我确信这是一个比嵌套np.where语句更好的方法,但它应该在这个给定的例子中工作。

import pandas as pd
import numpy as np
# Create dummy data
code = pd.Series(['0:1', '1:0', '0:1', '0:.', '.:1', '0:1'])
ref = pd.Series(['A', 'G', 'A', 'T', 'A', 'T'])
alt = pd.Series(['a', 'b', 'c', 'd', 'e', 'f'])

df = pd.DataFrame()

虚拟数据输出:

 code REF ALT
0  0:1   A   a
1  1:0   G   b
2  0:1   A   c
3  0:.   T   d
4  .:1   A   e
5  0:1   T   f

嵌套np.where允许您检查两个以上的条件。

# Split the code string into two columns
df[['code_start', 'code_end']]  = df['code'].str.split(':', expand=True)

# nested np.where to assign letters based on code for beginning of code column.
df['new_start'] = np.where(df['code_start']=='0', df['REF'], (np.where(df['code_start']=='1', df['ALT'], '0')))

# nested np.where to assign letters based on code for endof code column.
df['new_end'] = np.where(df['code_end']=='0', df['REF'], (np.where(df['code_end']=='1', df['ALT'], '0')))

# Create new code column combining columns as string.
df['new_code'] = df['new_start']+":"+df['new_end']

最终输出:

  code REF ALT code_start code_end new_start new_end new_code
0  0:1   A   a          0        1         A       a      A:a
1  1:0   G   b          1        0         b       G      b:G
2  0:1   A   c          0        1         A       c      A:c
3  0:.   T   d          0        .         T       0      T:0
4  .:1   A   e          .        1         0       e      0:e
5  0:1   T   f          0        1         T       f      T:f

从这里您可以删除额外的列。

我相信有一种更简洁的方法,也许使用re.sub但这是一种方法。

于 2021-08-04T14:43:26.907 回答