通过 R 中的行标签计算相对丰度? (素食套餐?)
Calculate relative abundance by row label in R? (vegan package?)
我正在尝试根据行标签或名称计算相对丰度(获取 df$path1
中每个测试的相对丰度。所以我想从 [=13] 计算计数的相对丰度=],并分别计算 test2
中计数的相对丰度。test1
中的相对丰度数之和等于 1。
我目前正在使用 vegan
软件包,但可以使用其他选项。
测试数据集:
library(vegan)
df <- data.frame(x = c("a", "b", "c", "d", "e"),
path1 = c("test1", "test1", "test2", "test2", "test3"),
value = c(40, 10, 34, 12, 20))
df$relabun <- decostand(df[3], 2, method = "total") #takes relative abundace of whole column
基于 df$path1
的相对丰度的理想输出如下所示:
x path1 relabun_bypath1
a test1 0.8
b test1 0.2
c test2 0.74
d test2 0.26
e test3 1
这是一道经典的拆分-应用-组合题。 base R 中最直接的方式是
- 用
split
、 按组拆分 data.frame
- 使用
*apply
和 应用函数
- 结合
do.call(rbind, ... )
或unlist
。
所以
unlist(lapply(split(df, df$path1), function(x){x$value / sum(x$value)}))
# test11 test12 test21 test22 test3
# 0.8000000 0.2000000 0.7391304 0.2608696 1.0000000
我们可以将其分配给一个新变量。然而,base 有一个很好的函数,虽然名字很奇怪,叫做 ave
,它可以为我们跨组应用一个函数:
ave(df$value, df$path1, FUN = function(x){x / sum(x)})
# [1] 0.8000000 0.2000000 0.7391304 0.2608696 1.0000000
这样更简洁,也可以赋值给新的变量。
如果您更喜欢 Hadleyverse,dplyr
的分组可以使过程更具可读性:
library(dplyr)
df %>% group_by(path1) %>% mutate(relAbundByPath = value / sum(value))
# Source: local data frame [5 x 4]
# Groups: path1 [3]
#
# x path1 value relAbundByPath
# (fctr) (fctr) (dbl) (dbl)
# 1 a test1 40 0.8000000
# 2 b test1 10 0.2000000
# 3 c test2 34 0.7391304
# 4 d test2 12 0.2608696
# 5 e test3 20 1.0000000
如您所见,它 returns 是 data.frame 的新版本,我们可以使用它来覆盖现有版本或制作新副本。
无论选择哪条路线,都要熟悉其中的逻辑,因为您很可能会经常使用它。更好的是,学习所有这些。以及 tapply
和 mapply
/Map
。 data.table
...为什么不呢?
注意: 如果愿意,您也可以用 prop.table
函数替换 value / sum(value))
结构。它更简洁(例如 ave(df$value, df$path1, FUN = prop.table)
),但它的作用不太明显,这就是我在这里没有使用它的原因。
我正在尝试根据行标签或名称计算相对丰度(获取 df$path1
中每个测试的相对丰度。所以我想从 [=13] 计算计数的相对丰度=],并分别计算 test2
中计数的相对丰度。test1
中的相对丰度数之和等于 1。
我目前正在使用 vegan
软件包,但可以使用其他选项。
测试数据集:
library(vegan)
df <- data.frame(x = c("a", "b", "c", "d", "e"),
path1 = c("test1", "test1", "test2", "test2", "test3"),
value = c(40, 10, 34, 12, 20))
df$relabun <- decostand(df[3], 2, method = "total") #takes relative abundace of whole column
基于 df$path1
的相对丰度的理想输出如下所示:
x path1 relabun_bypath1
a test1 0.8
b test1 0.2
c test2 0.74
d test2 0.26
e test3 1
这是一道经典的拆分-应用-组合题。 base R 中最直接的方式是
- 用
split
、 按组拆分 data.frame
- 使用
*apply
和 应用函数
- 结合
do.call(rbind, ... )
或unlist
。
所以
unlist(lapply(split(df, df$path1), function(x){x$value / sum(x$value)}))
# test11 test12 test21 test22 test3
# 0.8000000 0.2000000 0.7391304 0.2608696 1.0000000
我们可以将其分配给一个新变量。然而,base 有一个很好的函数,虽然名字很奇怪,叫做 ave
,它可以为我们跨组应用一个函数:
ave(df$value, df$path1, FUN = function(x){x / sum(x)})
# [1] 0.8000000 0.2000000 0.7391304 0.2608696 1.0000000
这样更简洁,也可以赋值给新的变量。
如果您更喜欢 Hadleyverse,dplyr
的分组可以使过程更具可读性:
library(dplyr)
df %>% group_by(path1) %>% mutate(relAbundByPath = value / sum(value))
# Source: local data frame [5 x 4]
# Groups: path1 [3]
#
# x path1 value relAbundByPath
# (fctr) (fctr) (dbl) (dbl)
# 1 a test1 40 0.8000000
# 2 b test1 10 0.2000000
# 3 c test2 34 0.7391304
# 4 d test2 12 0.2608696
# 5 e test3 20 1.0000000
如您所见,它 returns 是 data.frame 的新版本,我们可以使用它来覆盖现有版本或制作新副本。
无论选择哪条路线,都要熟悉其中的逻辑,因为您很可能会经常使用它。更好的是,学习所有这些。以及 tapply
和 mapply
/Map
。 data.table
...为什么不呢?
注意: 如果愿意,您也可以用 prop.table
函数替换 value / sum(value))
结构。它更简洁(例如 ave(df$value, df$path1, FUN = prop.table)
),但它的作用不太明显,这就是我在这里没有使用它的原因。