使用用户定义的函数,我必须加入数据帧中选定的列数的置信区间(称为CIlow
和CIhigh
)的下限和上限。数据框架包含CIlow
和CIhigh
,用于许多组(名为a
、b
和c
)和数字行(在本例中只有两个)。如下所示,数据框架是什么样的。
dataframe<-data.frame(CIlow_a=c(1.1,1.2),CIlow_b=c(2.1,2.2),CIlow_c=c(3.1,3.2),
CIhigh_a=c(1.3,1.4),CIhigh_b=c(2.3,2.4),CIhigh_c=c(3.3,3.4))
我希望在现有组( a
、b
和c
)中为选定的组(例如,a
、b
和c
)中的每个组设置一个联合列。
因此,预期产出应如下:
output<-data.frame(CI_a=c("(1.1,1.3)","(1.2,1.4)"),
CI_b=c("(2.1,2.3)","(2.2,2.4)"))
为了构建自己的用户定义函数,我尝试了以下代码:
f<-function(df,gr){
enquo_gr<-enquo(gr)
r<-df%>%
dplyr::mutate(UQ(paste("CI",quo_name(gr),sep="_")):=
sprintf("(%s,%s)",
paste("CIlow",UQ(enquo_gr),sep="_"),
paste("CIhigh",UQ(enquo_gr),sep="_")))%>%
dplyr::select(paste("CI",UQ(enquo_gr),sep="_"))
return(r)
}
但是,当以这种方式使用上述函数时
library(dplyr)
group<-c("a","b")
dataframe<-data.frame(CIlow_a=c(1.1,1.2),CIlow_b=c(2.1,2.2),CIlow_c=c(3.1,3.2),CIhigh_a=c(1.3,1.4),CIhigh_b=c(2.3,2.4),CIhigh_c=c(3.3,3.4))
f(df=dataframe,gr=group)
我收到以下错误消息:
错误:
expr
必须引用符号、标量或调用
我怎样才能解决这个问题?
PS1:这个问题类似于a previous one。但是,由于需要选择要合并的列,这个问题更进一步。
PS2:我希望遵循这个问题的方法来提供代码建议。
发布于 2017-07-21 15:00:11
我自己找到了解决问题的办法。以下代码起作用:
output<-data.frame(CI_a=c("(1.1,1.3)","(1.2,1.4)"), CI_b=c("(2.1,2.3)","(2.2,2.4)"))
dataframe<-data.frame(CIlow_a=c(1.1,1.2),CIlow_b=c(2.1,2.2),CIlow_c=c(3.1,3.2),
CIhigh_a=c(1.3,1.4),CIhigh_b=c(2.3,2.4),CIhigh_c=c(3.3,3.4))
f <- function(df, gr){
sl <<- rlang::syms(paste("CIlow", gr, sep="_"))
sh <<- rlang::syms(paste("CIhigh", gr, sep="_"))
nmN <<- paste("CI", gr, sep= "_")
r<-df
for(i in 1:length(gr)){
r<-dplyr::mutate(r,UQ(nmN[i]) := sprintf("(%s;%s)", UQ(sl[[i]]),UQ(sh[[i]])))
}
r<- dplyr::select(r,nmN)
return(r)
}
group <- c("a","b")
x<-f(df=dataframe, gr=group)
该代码适用于group
中未定义的元素数。因此,它适用于c("a","b")
、c("a")
或c("a","b","c")
。
我知道不推荐循环。如果有更好的解决方案,我们将不胜感激。
发布于 2017-07-09 18:27:48
如果要传递引号字符串,则使用sym
(用于返回list
的多个元素- syms
)。
f <- function(df, gr){
sl <- rlang::syms(paste("CIlow", gr, sep="_"))
sh <- rlang::syms(paste("CIhigh", gr, sep="_"))
nmN <- paste("CI", gr, sep= "_")
df %>%
dplyr::mutate(!!(nmN[1]) := sprintf("(%s,%s)",
!!(sl[[1]]), !!(sh[[1]])),
!!(nmN[2]) := sprintf("(%s,%s)",
!!(sl[[2]]), !!(sh[[2]]))) %>%
dplyr::select(paste("CI", gr, sep="_"))
}
group <- c("a","b")
f(dataframe, group)
# CI_a CI_b
#1 (1.1,1.3) (2.1,2.3)
#2 (1.2,1.4) (2.2,2.4)
发布于 2017-08-12 00:51:41
根据这个问题,我可能会回答不同的问题,但是在检查了您的答案之后,我准备了下面的代码。它使用技巧与lapply
,从这里dplyr::unite across column patterns。我不确定是否使用dplyr/tidyr
是最好的选择,也许简单的for
会更简单。
output <- data.frame(CI_a=c("(1.1,1.3)","(1.2,1.4)"),
CI_b=c("(2.1,2.3)","(2.2,2.4)"),
stringsAsFactors = F)
dataframe <- data.frame(CIlow_a=c(1.1,1.2),CIlow_b=c(2.1,2.2),CIlow_c=c(3.1,3.2),
CIhigh_a=c(1.3,1.4),CIhigh_b=c(2.3,2.4),CIhigh_c=c(3.3,3.4))
tricky <- function(input_data, group_ids){
# convert columns to character
input_data <- input_data %>%
mutate_each(funs(as.character(.)))
# unite selected groups
output <- group_ids %>%
lapply(function(group_id) {unite_(input_data,
paste0("CI_", group_id),
paste0(c("CIlow_", "CIhigh_"), group_id),
sep = ',') %>% select_(paste0("CI_", group_id))}) %>%
bind_cols() %>%
mutate_each(funs(paste0("(", ., ")")))
return(output)
}
identical(tricky(dataframe, list("a", "b")), output)
https://stackoverflow.com/questions/44998441
复制相似问题