For 循环转换为 apply/plyr

For Loop conversion to apply/plyr

我写了下面的代码,想通过使用 plyr 或 apply 来改进它,可惜我似乎无法让它工作。这个想法是识别正确的列,然后 extract/fetch 适当的值。

df <- data.frame(ID=c(1,2,3,4,5),COUNTRY=c('NL','FR','NL','BE','NL'),
             NL_GEN=c(5,5,10,20,5),FR_GEN=c(15,10,10,25,5),BE_GEN=c(10,10,5,15,5))

col_sel <- vector('numeric',length=nrow(df))
for ( i in 1:nrow(df)) {
  col_sel[i] <- as.numeric(df[i,grep(paste(df$COUNTRY[i],"_GEN",sep = ""),names(df))])
}

如何使用 plyr 或 apply 一次传递 1 行并且 return 单个值而不是整列?

感谢您提供的任何帮助。

我认为我们可以使用 plyr 包中的 adply

library(plyr)
adply(df, 1, function(x) c(Result = x[,which(grepl(x$COUNTRY, names(x)))]))

#   ID COUNTRY NL_GEN FR_GEN BE_GEN Result
# 1  1      NL      5     15     10      5
# 2  2      FR      5     10     10     10
# 3  3      NL     10     10      5     10
# 4  4      BE     20     25     15     15
# 5  5      NL      5      5      5      5

考虑 vapply()seq_along(),它允许您指定输出,这里是一个数字向量:

new_col_sel <- vapply(seq_along(df), function(i) {
      df[i, grep(paste0(df$COUNTRY[i], "_GEN"), names(df))]
}, numeric(1))

new_col_sel   
# [1]  5 10 10 15  5

all.equal(col_sel, new_col_sel)
# [1] TRUE 

如果需要向数据框添加列,只需分配它:

df$col_sel <- vapply(seq_along(df), function(i) {
     df[i, grep(paste0(df$COUNTRY[i], "_GEN"), names(df))]
}, numeric(1))

#   ID COUNTRY NL_GEN FR_GEN BE_GEN col_sel
# 1  1      NL      5     15     10       5
# 2  2      FR      5     10     10      10
# 3  3      NL     10     10      5      10
# 4  4      BE     20     25     15      15
# 5  5      NL      5      5      5       5