我需要生成一个热图,其中包含确定数量的箱内位置的平均覆盖范围,无论每个箱内转录组中的碱基数量如何。换句话说,如果我想要有 10 个 bin,对于一个转录组,它可能有 1000 个碱基分布在 10 个 bin 中,而另一个转录组可能有 2445 个碱基分布在 10 个 bin 中。
问题是在我的覆盖文件中,有一些空白不属于任何垃圾箱。例如,如果我想要 5 个垃圾箱超过 10 个位置,我将有:(0,2]、(2,4]、(4,6]、(6,8]、(8,10])。如果我的位置覆盖范围为 1, 5, 5, 5, 7, 7, 10,垃圾箱“(2,4]”将被隐藏,因此不会出现在热图中。我想要的是这些没有覆盖范围的垃圾箱被填充0,以便它们出现在热图中。
我正在将 python 与 pandas、seaborn 和 matplot.pyplot 库一起使用
在下图中,第一行是我的垃圾箱的边缘位置,数据框是垃圾箱的覆盖范围:
输入示例:
chr17 1 1
chr17 5 1
chr17 5 2
chr17 5 2
chr17 7 1
chr17 7 5
chr17 10 1
问题:
chr data_bin avg
chr17 (0,2] 1
chr17 (4,6] 1.66
chr17 (4,6] 1.66
chr17 (4,6] 1.66
chr17 (6,8] 3
chr17 (6,8] 3
chr17 (8,10] 1
预期:
chr data_bin avg
chr17 (0,2] 1
**chr17 (2,4] 0**
chr17 (4,6] 1.66
chr17 (4,6] 1.66
chr17 (4,6] 1.66
chr17 (6,8] 3
chr17 (6,8] 3
chr17 (8,10] 1
我使用的功能是:
def bins_calculator(path_txt:str, start:int,end:int):
column_names =["chr", "pos", "cov"]
data = pd.read_csv(path_txt, names = column_names, sep = '\t')
step = int((end - start) / 10)
n_bins = [start + i * step for i in range(11)]
n_bins[-1] = end
data["data_bin"] = pd.cut(data["pos"], bins = n_bins)
data["avg"] = data.groupby("data_bin", observed = False)["cov"].transform("mean")
filtered_data = data[["chr","data_bin","avg"]].drop_duplicates("data_bin")
return filtered_data
对此问题有任何疑问,请在评论中告诉我:)
IIUC 您可以使用
.merge
合并缺失的类别,然后用您想要的值填充任意 NaNs
:
df["data_bin"] = pd.cut(df["pos"], range(0, 12, 2))
df = pd.merge(
df,
df["data_bin"].cat.categories.to_frame(),
left_on="data_bin",
right_on=0,
how="outer",
)[["chr", "data_bin", "cov"]]
df["chr"] = df["chr"].ffill().bfill()
df["cov"] = df["cov"].fillna(0)
df["avg"] = df.groupby("data_bin")["cov"].transform("mean")
print(df)
打印:
chr data_bin cov avg
0 chr17 (0.0, 2.0] 1.0 1.000000
1 chr17 (2.0, 4.0] 0.0 0.000000
2 chr17 (4.0, 6.0] 1.0 1.666667
3 chr17 (4.0, 6.0] 2.0 1.666667
4 chr17 (4.0, 6.0] 2.0 1.666667
5 chr17 (6.0, 8.0] 1.0 3.000000
6 chr17 (6.0, 8.0] 5.0 3.000000
7 chr17 (8.0, 10.0] 1.0 1.000000