在列名中搜索字符串并检索每行的相应值

时间:2018-05-04 13:55:58

标签: r string dataframe subset

我有这样的df:

id <- c("defoo","ghfoo","abfoo")
abc <- c(.3,.1,.4)
ghi <- c(.4,.2,.2)
abc_dif <- c(.4,.3,.8)
def_dif <- c(.5,.7,.6)
ghi_dif <- c(.2,.1,.9)
df <- data.frame(id,abc,ghi,abc_dif,def_dif,ghi_dif)

我想查找名称中包含id行中值的前两个字符的列,并且还包括&#34; dif,&#34;并创建一个新列,其中包含每行的这些列中的相应值。

在此示例数据中,新列将是

df$result <- c(.5,.1,.8)

我的众多尝试涉及各种版本的sapply和apply,就像下面尝试简单地获取列索引一样:

df$result <- apply(substr(df[,which(colnames(df)=="id")],1,2),1,function(x) grep(x,colnames(df[which(grepl("dif",colnames(df),fixed=TRUE))]),fixed = TRUE))

这给出了错误:

"Error in apply(substr(df[, which(colnames(df) == "id")], 1, 2), 1, function(x) grep(x,  : 
  dim(X) must have a positive length"

这样做的最佳方式是什么?

3 个答案:

答案 0 :(得分:2)

我们可以创建一个row/column索引来获取值

df$result <- df[4:6][cbind(1:nrow(df), match( substr(df$id, 1, 2),
                substr(names(df)[4:6], 1, 2)))]

df$result
#[1] 0.5 0.1 0.8

答案 1 :(得分:1)

您可以尝试tidyverse

library(tidyverse)

df %>% 
  gather(k,v, -id:-ghi) %>% 
  filter(str_sub(id,1,2) == str_sub(k,1,2)) %>% 
  select(1,result=v) %>% 
  left_join(df, .)
     id abc ghi abc_dif def_dif ghi_dif result
1 defoo 0.3 0.4     0.4     0.5     0.2 0.5
2 ghfoo 0.1 0.2     0.3     0.7     0.1 0.1
3 abfoo 0.4 0.2     0.8     0.6     0.9 0.8

答案 2 :(得分:0)

您可以循环浏览df$id,然后为每一个选择df中的相关单元格:

df$result <- sapply(df$id, function(x) df[df$id == x,
                                          grepl(paste0(substring(x,1,2),".*dif"), names(df))])

df$result
#[1] 0.5 0.1 0.8