如何将lapply与mutate函数一起使用
您好,我正在尝试将lapply与mutate函数一起使用。我正在处理嵌套列表数据。
让我们举个例子。 given
是具有两个元素的嵌套列表。每个元素都是10 * 2列表。
given<-replicate(2,list(matrix(unlist(replicate(10,sample(c(0.2,0.3,0.4,0.1),2,replace=FALSE),simplify=FALSE)),ncol=2)))
colnames(given[[1]])<-c('a','b')
colnames(given[[2]])<-c('a','b')
given
我将0.1和0.2转换为“低”,将0.3转换为“中”,将0.4转换为“高”。我使用了lapply,mutate和if_else函数。
new_given<-lapply(seq_along(given), function(x){
mutate(x,
given[[x]][['new']] = if_else(given[[x]][['a']] %in% c(0.1,0.2),'low',
if_else(given[[x]][['I12']] %in% c(0.3),'middle','high')))})
但是,发生了错误。它说有一个'意外的')''。但是,括号中的数字是右配对的。
> new_given<-lapply(seq_along(given), function(x){
+ mutate(x,
+ given[[x]][['new']] = if_else(given[[x]][['a']] %in% c(0.1,0.2),'low',
Error: unexpected '=' in:
" mutate(x,
given[[x]][['new']] ="
> if_else(given[[x]][['I12']] %in% c(0.3),'middle','high')))})
Error: unexpected ')' in " if_else(given[[x]][['I12']] %in% c(0.3),'middle','high'))"
>
您能告诉我问题出在哪里以及如何解决吗?
*其他信息:我读了这篇文章,Using lapply with mutate in R 但是,它使用data.frame,而不处理列表数据。因此,方法似乎有所不同。
答案 0 :(得分:1)
首先,您要获得矩阵列表,而不是数据帧列表。另外,您可以在此处将lapply
引向given
而不是进行seq_along
library(dplyr)
lapply(given, function(x) {
data.frame(x) %>%
mutate(new = if_else(a %in% c(0.1,0.2),'low',
if_else(a %in% c(0.3),'middle','high')))})
#[[1]]
# a b new
#1 0.2 0.1 low
#2 0.1 0.2 low
#3 0.4 0.4 high
#4 0.3 0.2 middle
#5 0.1 0.3 low
#6 0.3 0.1 middle
#7 0.4 0.2 high
#8 0.1 0.3 low
#9 0.3 0.1 middle
#10 0.4 0.3 high
#[[2]]
# a b new
#1 0.3 0.1 middle
#2 0.1 0.3 low
#3 0.3 0.1 middle
#4 0.2 0.3 low
#5 0.1 0.4 low
#6 0.4 0.1 high
#7 0.1 0.2 low
#8 0.2 0.3 low
#9 0.4 0.4 high
#10 0.3 0.1 middle
此外,更好的方法是将方法分开。因此,纯基础R解决方案就是
lapply(given, function(x)
transform(data.frame(x),
new = ifelse(a %in% c(0.1,0.2),'low',ifelse(a %in% c(0.3),'middle','high'))))
而您更喜欢tidyverse
map(given, ~ data.frame(.) %>%
mutate(new = if_else(a %in% c(0.1,0.2),'low',
if_else(a %in% c(0.3),'middle','high'))))
答案 1 :(得分:1)
您的方法有很多问题。首先,您遇到的错误只是在发生第一个错误(意外的'=')之后复制其余行的副作用。
错误的原因不同。您正在将mutate应用于x
。 x
是长度为1的数字矢量。但是,mutate
仅适用于数据帧(甚至不包括矩阵!)。不过,您可以先将矩阵转换为data.frames(正如Ronak在另一个答案中所建议的那样)。
最后,您的矩阵是两倍。您的方法可能大部分时间都有效,但不能保证始终有效,因为即使数字看起来像0.3,实际上也可能是0.3000000000000000001,在这种情况下,%in% 0.3
返回FALSE
。现在看来似乎不太可能,但请相信我,这种方法迟早会伤害您并且您不会看到它来的。我是凭经验说话的。
让我们首先创建一个采用矩阵的函数,并根据其第一列确定其应为“低”,“中”还是“高”。
cut
函数需要多个中断,并为每个数字分配一个表示给定间隔的因子级别:
cut(given[[1]][,1], c(-Inf, 0.2, 0.3, Inf))
结果:
[1] (0.3, Inf] (-Inf,0.2] (-Inf,0.2] (0.3, Inf] (-Inf,0.2] (0.3, Inf]
[7] (-Inf,0.2] (-Inf,0.2] (0.3, Inf] (-Inf,0.2]
Levels: (-Inf,0.2] (0.2,0.3] (0.3, Inf]
我们可以直接为结果分配标签:
cut(given[[1]][,1], c(-Inf, 0.2, 0.3, Inf), labels=c("low", "mid", "high"))
我们可以将其变成一个函数:
mklevels <- function(mtx) {
cut(mtx[,1], c(-Inf, 0.2, 0.3, Inf), labels=c("low", "mid", "high"))
}
不是将矩阵转换为数据帧并添加新列,而是为什么不创建每个矩阵只有一列的新数据框:
data.frame(sapply(given, mklevels))
这样做的好处是,如果矩阵很大并且用于其他计算目的,则将它们更改为数据帧不是一种有效的方法。
如果您确实希望使用%in%
,然后将数据转换为因数。这样,您将能够检查因子水平并查看是否存在问题。例如:
x <- c(0.3, 0.2, 0.3 + 1e-11, 0.1)
x
看起来足够无辜:
> x
[1] 0.3 0.2 0.3 0.1
但是,x[4] %in% .3
返回FALSE
。但是将其转换为一个因子并查看其水平:
factor(x)
[1] 0.3 0.2 0.30000000001 0.1
Levels: 0.1 0.2 0.3 0.30000000001
一旦将数据转换为因子,就可以安全地采用Ronak的方法。但是我永远不会尝试使用数字向量!