将值映射到不同变量的组中

时间:2015-07-06 12:15:49

标签: r

我想创建一个函数来将值映射到组和不同的变量。

df <- data.frame(x = c("a", "a", "b", "c", "c", "d", "e"), 
                 y = c(1, 5, 5, 1, 6, 8, 3), 
                 z = runif(7), 
                 stringsAsFactors = FALSE)

例如对于这些数据,对于变量x,我想将值“a”,“b”映射到“label1”,将“c”“d”“e”映射到“label2”,并将变量y映射到将1,3映射为“code1”,将5,6,8映射为“code2”。

groups <- list(x = list(label1 = c("a", "b"), label2 = c("c", "d", "e")), 
                  y = list(code1 = c(1, 3), code2 = c(5, 6, 8)))

在这个例子中,我想要映射来自2个变量的值,但它可以是1,3,4 ......所以我不想为每个变量创建数据帧查找或逐个分配每个变量。这就是为什么我使用一个列表(我在函数参数中发现它更友好)并且不能使用$。 +这是在函数内部使用的,所以我不需要任何硬编码。

所以实际上我创建了这个函数:

f <- function(x, groups) {

  table <- reshape2::melt(groups)
  table <- split(table, table$L1)

  for (i in seq_along(table)) {
    x[names(table)[i]] <- table[[i]]$L2[match(x[,names(table)[i]], table[[i]]$value)]
  }
  return(x)
}

这是我尝试使用嵌套列表获得“友好”群组参数的最佳方法。

我尝试了类似dplyr::mutate的语法,例如myFunction(x = list(label1 = c("a", "b"), label2 = c("c", "d", "e")), y = list(code1 = c(1, 3), code2 = c(5, 6, 8)))这可能非常好,但这只是一个有很多参数的更大函数的一部分所以我认为这不可行(至少我没有成功)。

但我确信有更好的方法可以做到这一点,或者可能已经存在功能。 你有改进的想法吗?谢谢!

4 个答案:

答案 0 :(得分:6)

您可以使用Grid尝试使用data.frames作为对应关系:

match

编辑考虑到“新”问题的限制,您可以执行此操作,保持# define the correspondences df2 <- data.frame(v1=letters[1:5], v2=paste0("label", c(1,1,2,2,2)), stringsAsFactors=F) df3 <- data.frame(v1=c(1, 3, 5, 6, 8), v2=paste0("code", c(1,1,2,2,2)), stringsAsFactors=F) # change your variables df$x <- df2$v2[match(df$x, df2$v1)] df$y <- df3$v2[match(df$y, df3$v1)] df不变:

groups

答案 1 :(得分:2)

这种方法与@ MarkeD一样,将编码放在新列中:

library(data.table)
setDT(df)
mymaps <- lapply(groups, stack)
for (nm in names(mymaps)){
    setkeyv(df,nm)
    df[mymaps[[nm]], paste0(nm,"_new") := ind]
}

要覆盖变量,您可以添加df[,(nm):=NULL]setnames(df,paste0(nm,"_new"),nm)

答案 2 :(得分:1)

这个怎么样 - 根据需要制作一个命名查找列表:

groups <- list(a = 'label1', b='label1', c='label2',d='label2',e='label2', 
              '1'='code1', '3' = 'code1', '5' = 'code2','6' = 'code2','7' = 'code2' )

小心使用数字作为名称,因为它将默认为位置。

然后你可以使用子集来获得你的比赛:

## generate the data frame example:
df <- data.frame(x = c("a", "a", "b", "c", "c", "d", "e"), 
                   y = c(1, 5, 5, 1, 6, 8, 3), 
                   z = runif(7), 
                   stringsAsFactors = FALSE)

df$group_x <- groups[df$x]

## using as.character to avoid numbers throwing off the lookup
df$group_y <- groups[as.character(df$y)]

创建:

 x y         z group_x group_y
 a 1 0.1684421  label1   code1
 a 5 0.7459545  label1   code2
 b 5 0.5308211  label1   code2
 c 1 0.6637787  label2   code1
 c 6 0.3493355  label2   code2
 d 8 0.8303369  label2   code2
 e 3 0.8727316  label2   code1

答案 3 :(得分:1)

或者:

df[,'x'] <- ifelse(df[,'x'] %in% c('a', 'b'), 'label1', 'label2')
df[,'y'] <- ifelse(df[,'y'] %in% c(1,3), 'code1', 'code2')
#        x     y         z
# 1 label1 code1 0.4536355
# 2 label1 code2 0.2827496
# 3 label1 code2 0.8643375
# 4 label2 code1 0.9481302
# 5 label2 code2 0.8662686
# 6 label2 code2 0.4208953
# 7 label2 code1 0.4438536