如何计算数据集中每列与第一列的乘积之和?

4

我有以下的数据帧:

df <- data.frame(stat = c(3.38, -3.40, 4.45, -4.21, 3.33), 
                 patient1 = c(-0.44, -0.22, 0.80, -0.21, -0.22),
                 patient2 = c(0.40, 0.045, -0.14, -0.078, -0.16),
                 patient3 = c(0.35, 0.21, -0.23, -0.019, -0.21),
                 row.names = c("gene1","gene2","gene3","gene4","gene5"))

> df
       stat patient1 patient2 patient3
gene1  3.38    -0.44    0.400    0.350
gene2 -3.40    -0.22    0.045    0.210
gene3  4.45     0.80   -0.140   -0.230
gene4 -4.21    -0.21   -0.078   -0.019
gene5  3.33    -0.22   -0.160   -0.210

我一直在苦苦寻找如何编写脚本或循环来计算“stat”列和每个患者列的乘积总和,因为我的患者数据集中有141列和142行需要完成此工作。

因此,我想要一个名为“Signature Score”的新行,其计算值如下:

row.names(df)[nrow(df)] <- "Signature Score"

sum_multi_1 <- sum(df[c(1:nrow(df)-1),2]*df[c(1:nrow(df)-1),1])
sum_multi_2 <- sum(df[c(1:nrow(df)-1),3]*df[c(1:nrow(df)-1),1])
sum_multi_3 <- sum(df[c(1:nrow(df)-1),4]*df[c(1:nrow(df)-1),1])

df[nrow(df),2] <- sum_multi_1
df[nrow(df),3] <- sum_multi_2
df[nrow(df),4] <- sum_multi_3

which is...

> df
                 stat patient1 patient2 patient3
gene1            3.38  -0.4400  0.40000  0.35000
gene2           -3.40  -0.2200  0.04500  0.21000
gene3            4.45   0.8000 -0.14000 -0.23000
gene4           -4.21  -0.2100 -0.07800 -0.01900
gene5            3.33  -0.2200 -0.16000 -0.21000
Signature Score    NA   2.9723  0.37158 -1.17381

我试图制作一个类似这样的for循环...
for (i in 1:nrow(df)){
  df[nrow(df),i+1] <- sum(df[c(1:nrow(df)-1,i+1)]*df[c(1:nrow(df)-1),1])
}

但它没有完成任务。请问有人能告诉我我错了什么或需要写什么吗?

祝一切顺利, Tj

5个回答

4
你可以使用mutateacross计算所需的乘法,然后使用janitor包中的adorn_totals()添加总列。
   library(dplyr)
    df <- data.frame(stat = c(3.38, -3.40, 4.45, -4.21, 3.33), 
                       patient1 = c(-0.44, -0.22, 0.80, -0.21, -0.22),
                       patient2 = c(0.40, 0.045, -0.14, -0.078, -0.16),
                       patient3 = c(0.35, 0.21, -0.23, -0.019, -0.21),
                       row.names = c("gene1","gene2","gene3","gene4","gene5")) %>% 
  rownames_to_column(var = "genes") %>% 
  mutate(across(patient1:patient3, ~.x * stat)) %>% 
  janitor::adorn_totals(name = "Signature Score") 
  
  df[length(df)+1, 2] <- NA

输出:

    rowname  stat patient1 patient2 patient3
           gene1  3.38  -1.4872  1.35200  1.18300
           gene2 -3.40   0.7480 -0.15300 -0.71400
           gene3  4.45   3.5600 -0.62300 -1.02350
           gene4 -4.21   0.8841  0.32838  0.07999
           gene5  3.33  -0.7326 -0.53280 -0.69930
 Signature Score    NA   2.9723  0.37158 -1.17381

2

我注意到你减去了1,以便让索引从0开始。然而,与Python不同,在R中,索引从1开始。所以你可能想要这个:

colSums(df[-1]*df$stat)
# patient1 patient2 patient3 
#  2.97230  0.37158 -1.17381 

2

另一种可能的解决方案,使用基础R语言:

rbind(df, signa = c(NA,colSums(df[,1] * df[-1])))

#>        stat patient1 patient2 patient3
#> gene1  3.38  -0.4400  0.40000  0.35000
#> gene2 -3.40  -0.2200  0.04500  0.21000
#> gene3  4.45   0.8000 -0.14000 -0.23000
#> gene4 -4.21  -0.2100 -0.07800 -0.01900
#> gene5  3.33  -0.2200 -0.16000 -0.21000
#> signa    NA   2.9723  0.37158 -1.17381

1

这里有另一种使用 tidyverse 的选项,我使用 summarise 函数来应用它,然后获取列总计,接着更改行名称,最后再绑定回原始数据框。

library(tidyverse)

df %>%
  summarise(across(-stat, ~ sum(.x * stat, na.rm = T))) %>%
  `row.names<-`("Signature Score") %>%
  bind_rows(df, .)

输出

                 stat patient1 patient2 patient3
gene1            3.38  -0.4400  0.40000  0.35000
gene2           -3.40  -0.2200  0.04500  0.21000
gene3            4.45   0.8000 -0.14000 -0.23000
gene4           -4.21  -0.2100 -0.07800 -0.01900
gene5            3.33  -0.2200 -0.16000 -0.21000
Signature Score    NA   2.9723  0.37158 -1.17381

1
你过于复杂化了。 为了让代码更清晰,定义一个辅助函数 fun 来进行列的乘法和求和。然后将该函数应用到数据中。
df <- data.frame(stat = c(3.38, -3.40, 4.45, -4.21, 3.33), 
                 patient1 = c(-0.44, -0.22, 0.80, -0.21, -0.22),
                 patient2 = c(0.40, 0.045, -0.14, -0.078, -0.16),
                 patient3 = c(0.35, 0.21, -0.23, -0.019, -0.21),
                 row.names = c("gene1","gene2","gene3","gene4","gene5"))

# auxiliary function
fun <- function(x, y) sum(x * y)

apply(df[-1], 2, fun, y = df[[1]])
#> patient1 patient2 patient3 
#>  2.97230  0.37158 -1.17381

sigscore <- apply(df[-1], 2, fun, y = df[[1]])
rbind(df, `Signature Score` = c(NA, sigscore))
#>                  stat patient1 patient2 patient3
#> gene1            3.38  -0.4400  0.40000  0.35000
#> gene2           -3.40  -0.2200  0.04500  0.21000
#> gene3            4.45   0.8000 -0.14000 -0.23000
#> gene4           -4.21  -0.2100 -0.07800 -0.01900
#> gene5            3.33  -0.2200 -0.16000 -0.21000
#> Signature Score    NA   2.9723  0.37158 -1.17381

本文内容是关于IT技术的,创建于2022-05-05,使用了reprex软件包(v2.0.1)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接