Pandas 数据框到嵌套计数器字典
Pandas dataframe to nested counter dictionary
我见过很多关于如何将 pandas 数据帧转换为嵌套字典的问题,但其中 none 涉及聚合信息。我什至可以在 pandas 内完成我需要的事情,但我被卡住了。
输入
我有一个如下所示的数据框:
FeatureID gene Target pos bc_count
0 1_1_1 NRAS_3 TAGCAC 0 0.42
1 1_1_1 NRAS_3 TGCACA 1 1.00
2 1_1_1 NRAS_3 GCACAA 2 0.50
3 1_1_1 NRAS_3 CACAAA 3 2.00
4 1_1_1 NRAS_3 CAGAAA 3 0.42
# create df as below
import pandas as pd
df = pd.DataFrame([{"FeatureID":"1_1_1", "gene":"NRAS_3", "Target":"TAGCAC",
"pos":0, "bc_count":.42},
{"FeatureID":"1_1_1", "gene":"NRAS_3", "Target":"TGCACA", "pos":1,
"bc_count":1.00},
{"FeatureID":"1_1_1", "gene":"NRAS_3", "Target":"GCACAA", "pos":2,
"bc_count":0.50},
{"FeatureID":"1_1_1", "gene":"NRAS_3", "Target":"CACAAA", "pos":3,
"bc_count":2.00},
{"FeatureID":"1_1_1", "gene":"NRAS_3", "Target":"CAGAAA", "pos":4,
"bc_count":0.42}])
问题
我需要将每一行的目标列拆分为 return 元组(位置、字母、计数),其中起始位置在 "pos" 列中给出,然后枚举后面每个位置的字符串,计数是在 "bc_count" 列中为该行找到的值。
例如,在第一行中,所需的元组列表为:
[(0, "T", 0.42), (1,"A", 0.42), (2,"G", 0.42), (3,"C", 0.42), (4,"A", 0.42), (5,"C", 0.42)]
我试过的
我创建了将目标列分解为找到的位置的代码,return创建一个位置元组、核苷酸(字母)并计算该字母,并将它们作为一列添加到数据框:
def index_target(row):
count_list = [((row.pos + x),y,
row.bc_count) for x,y in
enumerate(row.Target)]
df['pos_count'] = df.apply(self.index_target, axis=1)
其中 return 是基于该行的目标列的每一行的元组列表。
我需要为每个目标获取 df 中的每一行,并对计数求和。这就是为什么我想到使用字典作为计数器的原因:
position[letter] += bc_count
我试过创建一个 defaultdict,但它是单独附加每个元组列表,而不是对每个位置的计数求和:
from collections import defaultdict
d = defaultdict(dict) # also tried defaultdict(list) here
for x,y,z in row.pos_count:
d[x][y] += z
期望的输出
对于数据框中的每个特征,下面的数字代表每个位置在 bc_count 列中找到的单个计数的总和,x 代表找到联系的位置,没有一个字母可以是 return编辑为最大值:
pos A T G C
0 25 80 25 57
1 32 19 100 32
2 27 18 16 27
3 90 90 90 90
4 10 42 37 18
共识= TGXXT
不确定如何获得所需的输出,但我创建了列表 d
,其中包含数据框所需的元组。希望它能为您想要创建的内容提供一些指导:
d = []
for t,c,p in zip(df.Target,df.bc_count,df.pos):
d.extend([(p,c,i) for i in list(t)])
df_new = pd.DataFrame(d, columns = ['pos','count','val'])
df_new = df_new.groupby(['pos','val']).agg({'count':'sum'}).reset_index()
df_new.pivot(index = 'pos', columns = 'val', values = 'count')
这可能不是最优雅的解决方案,但我认为它可能会满足您的需求:
new_df = pd.DataFrame(
df.apply(
# this lambda is basically the same thing you're doing,
# but we create a pd.Series with it
lambda row: pd.Series(
[(row.pos + i, c, row.bc_count) for i, c in enumerate(row.Target)]
),
axis=1)
.stack().tolist(),
columns=["pos", "nucl", "count"]
)
其中 new_df
看起来像这样:
pos nucl count
0 0 T 0.42
1 1 A 0.42
2 2 G 0.42
3 3 C 0.42
4 4 A 0.42
5 5 C 0.42
6 1 T 1.00
7 2 G 1.00
8 3 C 1.00
9 4 A 1.00
然后我将旋转它以获得聚合计数:
nucleotide_count_by_pos = new_df.pivot_table(
index="pos",
columns="nucl",
values="count",
aggfunc="sum",
fill_value=0
)
其中 nucleotide_count_by_pos
看起来像:
nucl A C G T
pos
0 0.00 0.00 0.00 0.42
1 0.42 0.00 0.00 1.00
2 0.00 0.00 1.92 0.00
3 0.00 4.34 0.00 0.00
4 4.34 0.00 0.00 0.00
然后达成共识:
def get_consensus(row):
max_value = row.max()
nuc = row.idxmax()
if (row == max_value).sum() == 1:
return nuc
else:
return "X"
consensus = ''.join(nucleotide_count_by_pos.apply(get_consensus, axis=1).tolist())
对于您的示例数据,这将是:
'TTGCACAAA'
我见过很多关于如何将 pandas 数据帧转换为嵌套字典的问题,但其中 none 涉及聚合信息。我什至可以在 pandas 内完成我需要的事情,但我被卡住了。
输入
我有一个如下所示的数据框:
FeatureID gene Target pos bc_count
0 1_1_1 NRAS_3 TAGCAC 0 0.42
1 1_1_1 NRAS_3 TGCACA 1 1.00
2 1_1_1 NRAS_3 GCACAA 2 0.50
3 1_1_1 NRAS_3 CACAAA 3 2.00
4 1_1_1 NRAS_3 CAGAAA 3 0.42
# create df as below
import pandas as pd
df = pd.DataFrame([{"FeatureID":"1_1_1", "gene":"NRAS_3", "Target":"TAGCAC",
"pos":0, "bc_count":.42},
{"FeatureID":"1_1_1", "gene":"NRAS_3", "Target":"TGCACA", "pos":1,
"bc_count":1.00},
{"FeatureID":"1_1_1", "gene":"NRAS_3", "Target":"GCACAA", "pos":2,
"bc_count":0.50},
{"FeatureID":"1_1_1", "gene":"NRAS_3", "Target":"CACAAA", "pos":3,
"bc_count":2.00},
{"FeatureID":"1_1_1", "gene":"NRAS_3", "Target":"CAGAAA", "pos":4,
"bc_count":0.42}])
问题
我需要将每一行的目标列拆分为 return 元组(位置、字母、计数),其中起始位置在 "pos" 列中给出,然后枚举后面每个位置的字符串,计数是在 "bc_count" 列中为该行找到的值。
例如,在第一行中,所需的元组列表为:
[(0, "T", 0.42), (1,"A", 0.42), (2,"G", 0.42), (3,"C", 0.42), (4,"A", 0.42), (5,"C", 0.42)]
我试过的
我创建了将目标列分解为找到的位置的代码,return创建一个位置元组、核苷酸(字母)并计算该字母,并将它们作为一列添加到数据框:
def index_target(row):
count_list = [((row.pos + x),y,
row.bc_count) for x,y in
enumerate(row.Target)]
df['pos_count'] = df.apply(self.index_target, axis=1)
其中 return 是基于该行的目标列的每一行的元组列表。
我需要为每个目标获取 df 中的每一行,并对计数求和。这就是为什么我想到使用字典作为计数器的原因:
position[letter] += bc_count
我试过创建一个 defaultdict,但它是单独附加每个元组列表,而不是对每个位置的计数求和:
from collections import defaultdict
d = defaultdict(dict) # also tried defaultdict(list) here
for x,y,z in row.pos_count:
d[x][y] += z
期望的输出
对于数据框中的每个特征,下面的数字代表每个位置在 bc_count 列中找到的单个计数的总和,x 代表找到联系的位置,没有一个字母可以是 return编辑为最大值:
pos A T G C
0 25 80 25 57
1 32 19 100 32
2 27 18 16 27
3 90 90 90 90
4 10 42 37 18
共识= TGXXT
不确定如何获得所需的输出,但我创建了列表 d
,其中包含数据框所需的元组。希望它能为您想要创建的内容提供一些指导:
d = []
for t,c,p in zip(df.Target,df.bc_count,df.pos):
d.extend([(p,c,i) for i in list(t)])
df_new = pd.DataFrame(d, columns = ['pos','count','val'])
df_new = df_new.groupby(['pos','val']).agg({'count':'sum'}).reset_index()
df_new.pivot(index = 'pos', columns = 'val', values = 'count')
这可能不是最优雅的解决方案,但我认为它可能会满足您的需求:
new_df = pd.DataFrame(
df.apply(
# this lambda is basically the same thing you're doing,
# but we create a pd.Series with it
lambda row: pd.Series(
[(row.pos + i, c, row.bc_count) for i, c in enumerate(row.Target)]
),
axis=1)
.stack().tolist(),
columns=["pos", "nucl", "count"]
)
其中 new_df
看起来像这样:
pos nucl count
0 0 T 0.42
1 1 A 0.42
2 2 G 0.42
3 3 C 0.42
4 4 A 0.42
5 5 C 0.42
6 1 T 1.00
7 2 G 1.00
8 3 C 1.00
9 4 A 1.00
然后我将旋转它以获得聚合计数:
nucleotide_count_by_pos = new_df.pivot_table(
index="pos",
columns="nucl",
values="count",
aggfunc="sum",
fill_value=0
)
其中 nucleotide_count_by_pos
看起来像:
nucl A C G T
pos
0 0.00 0.00 0.00 0.42
1 0.42 0.00 0.00 1.00
2 0.00 0.00 1.92 0.00
3 0.00 4.34 0.00 0.00
4 4.34 0.00 0.00 0.00
然后达成共识:
def get_consensus(row):
max_value = row.max()
nuc = row.idxmax()
if (row == max_value).sum() == 1:
return nuc
else:
return "X"
consensus = ''.join(nucleotide_count_by_pos.apply(get_consensus, axis=1).tolist())
对于您的示例数据,这将是:
'TTGCACAAA'