【发布时间】:2017-07-21 02:38:04
【问题描述】:
我正在处理一个包含 5 列的数据表:
gene_id, length, sample1_count, sample2_count, sample3_count
我想在现有表中添加 3 个新列,这些列代表样本 1、样本 2 和样本 3 的标准化计数(即将每个基因的每个样本计数除以计数总数)。
如何创建 3 个新列?或者我第一次在unix中生成文件时需要这样做吗?
【问题讨论】:
标签: r
我正在处理一个包含 5 列的数据表:
gene_id, length, sample1_count, sample2_count, sample3_count
我想在现有表中添加 3 个新列,这些列代表样本 1、样本 2 和样本 3 的标准化计数(即将每个基因的每个样本计数除以计数总数)。
如何创建 3 个新列?或者我第一次在unix中生成文件时需要这样做吗?
【问题讨论】:
标签: r
我们可以使用data.table的方式来做到这一点
library(data.table)
nm1 <- grep("^sample\\d+_count", names(df1), value = TRUE)
setDT(df1)[, paste0("Norm_", nm1) := lapply(.SD, `/`, .N), gene_id, .SDcols = nm1]
如果是除以sum
setDT(df1)[, paste0("Norm_", nm1) := lapply(.SD, function(x) x/sum(x)),
gene_id, .SDcols = nm1]
【讨论】:
包含一个最小可重现示例可能会有所帮助,但以下将调用一个函数,用于将字段除以 mtcars 数据集中的柱面数,并将输出存储在新变量名下:
mtcars
fields_input <- c('hp', 'disp')
fields_output <- c('hp_per_cyl', 'disp_per_cyl')
divide_by_cyl <- function(v) v / mtcars[['cyl']]
mtcars[fields_output] <- lapply(mtcars[fields_input], divide_by_cyl)
mtcars
【讨论】:
在我看来,您的数据可以使用长格式更好地表示。使用长格式并使用data.table,您的问题会变得更加简单:
# Some sample data
dt <- data.table(
gene_id = sample(LETTERS, 10),
length = sample(1:25, 10),
sample1 = sample(1:1000, 10),
sample2 = sample(1:1000, 10),
sample3 = sample(1:1000, 10))
# Convert to long format
dt_long = melt(dt, id.vars = c("gene_id", "length"), value.name = "count")
# Calculate your normalized counts for each gene_id / length combination
dt_long[, normalized_count := count / sum(count), by = c("gene_id", "length")]
如果您再次需要宽格式输出,您可以随时使用:
dcast(dt_long, gene_id + length ~ variable)
得到:
gene_id length sample1 sample2 sample3
1: B 16 0.2666667 0.05232068 0.68101266
2: C 6 0.7737226 0.01459854 0.21167883
3: J 3 0.4131455 0.41549296 0.17136150
4: P 13 0.4846847 0.44054054 0.07477477
5: Q 23 0.3425573 0.11545802 0.54198473
6: R 12 0.6018576 0.21114551 0.18699690
7: S 4 0.5416924 0.30759728 0.15071032
8: T 24 0.1838666 0.40694006 0.40919333
9: X 11 0.4468085 0.45319149 0.10000000
10: Z 20 0.2267706 0.43144899 0.34178038
【讨论】:
这是一些可重复的数据:
set.seed(1)
df <- data.frame(gene_id = 1:5,
length = sample(1:100, 5),
sample1_count = sample(1:10, 5),
sample2_count = sample(1:10, 5),
sample3_count = sample(1:10, 5))
这是如何通过样本计数进行归一化、重命名归一化列并最终将归一化列连接到原始数据框(使用基本 R 函数):
norms <- sapply(df[ c("sample1_count", "sample2_count", "sample3_count")], function(x) x/sum(x))
colnames(norms) <- sub("count", "norm", colnames(norms))
df2 <- cbind(df, norms)
以下是标准化计数:
df2[, c("gene_id", "length", "sample1_norm", "sample2_norm", "sample3_norm")]
gene_id length sample1_norm sample2_norm sample3_norm
1 1 27 0.29032258 0.11538462 0.15151515
2 2 37 0.32258065 0.07692308 0.21212121
3 3 57 0.19354839 0.23076923 0.24242424
4 4 89 0.16129032 0.38461538 0.09090909
5 5 20 0.03225806 0.19230769 0.30303030
【讨论】: