在列表中查找包含R中vector的值的对象

时间:2018-01-01 13:20:38

标签: r list object conditional-statements

我的数据框

set.seed(1)
df <- data_frame(col1 = c(1:49), col2 = sample(c(0:20), 49, replace = T))

我的清单

fields <- list(A = c(2:4, 12:16, 24:28, 36:40, 48:49), 
           B = c(6:10, 18:22, 30:34, 42:46))

我想创建一个新列,其中包含字段中(矢量)对象的名称,其中包含df $ col1中的数字

我在字段上创建了一个条件循环

col1 <- df$col1

for (i in col1) {

if (col1[i] %in% fields[[1]] == T) {
col1[i] <- names(fields)[1]

}  else if (col1[i] %in% fields[[2]] == T) {
col1[i] <- names(fields)[2]

 }
}

虽然这样可行,但我可以将生成的新向量col1分配给我的数据框,这对我来说似乎并不高效 - 特别是因为我还有更多对象的列表。 我想这样做的原因是:我想使用ggplot和dplyr根据它们在我的列表中的位置( fields ,还有其他列表)对观察结果进行分组和汇总。我希望从我的问题中可以清楚地知道我打算做什么。谢谢!

修改

我创建了一个更通用的函数,它包含一个嵌套的for循环

find_object <- function(x, list) {  

for (j in 1:length(list)) {
  for (i in 1:length(x)) {

if (x[i] %in% list[[j]] == TRUE) {
  x[i] <- names(list)[j]
   }
  }
 }
x
}

find_object(col1, fields)

这或多或少是我想要的 - 但这是一个嵌套的for循环,我听说这很糟糕......有没有人有更好的解决方案? 感谢

2 个答案:

答案 0 :(得分:2)

更好的方法是将list转换为data.frame,然后进行加入/合并:

library(dplyr)
fields.df <- stack(fields) %>% mutate(ind = as.character(ind))
df %>% left_join(fields.df, by = c('col1' = 'values'))
#     col1  col2   ind
#    <int> <int> <chr>
#  1     1     5  <NA>
#  2     2     7     A
#  3     3    12     A
#  4     4    19     A
#  5     5     4  <NA>
#  6     6    18     B
#  7     7    19     B
#  8     8    13     B
#  9     9    13     B
# 10    10     1     B

注意:我使用left_join中的dplyr,因为您使用的是data_frame。基础R merge也应该有用。

答案 1 :(得分:1)

另一种方法是在使用match()创建数据框后使用stack()

library(dplyr)

foo <- stack(fields)
mutate(df, whatever = foo$ind[match(df$col1, foo$values)])

    col1  col2 whatever
   <int> <int> <fctr>  
 1     1     5 <NA>    
 2     2     7 A       
 3     3    12 A       
 4     4    19 A       
 5     5     4 <NA>    
 6     6    18 B       
 7     7    19 B       
 8     8    13 B       
 9     9    13 B       
10    10     1 B