迭代dplyr中的列

时间:2016-06-16 01:36:46

标签: r dplyr

我试图通过数据库的列逐步迭代一个函数。有哪些选择?我是否仅限于for循环或是否有dplyr方法或类似的直观代码结构我可以使用?

基本上我有一个比下面构造的矩阵大得多的矩阵,但具有相同的一般结构。第一列说明要选择哪个版本作为精炼数据收集,然后说明包含这三个版本中的每一个的所有数据。

library(dplyr)

# Function: creates a matrix of random strings, v = versionNumber
matADv.maker <- function (v){ 
    matADv <- data.frame(matrix(sample(letters[1:26], 10), nrow = 5))
    colnames(matADv) <- paste0("v", v, "_", letters[24:25])
    return(matADv)
}

set.seed(1)
lvl <- data.frame(c(as.integer(runif(5, 5, 8))))
colnames(lvl) <- "Level"
matADv5 <- matADv.maker(5)
matADv6 <- matADv.maker(6)
matADv7 <- matADv.maker(7)
matComp <- bind_cols(lvl, matADv5, matADv6, matADv7)
matComp
Source: local data frame [5 x 8]
  rowname Level  v5_x  v5_y  v6_x  v6_y  v7_x  v7_y
    (chr) (int) (chr) (chr) (chr) (chr) (chr) (chr)
1       1     5     x     e     m     t     k     z
2       2     6     z     d     r     e     a     l
3       3     6     p     n     x     z     j     x
4       4     7     o     g     i     c     u     d
5       5     5     b     s     y     u     h     o

我想知道是否有一些简单的方法可以沿着数据帧移动函数。

基本上,如何使用dplyr或类似的简单构造而不是循环来迭代列?

2 个答案:

答案 0 :(得分:1)

您可以通过利用列名称的规律性来避免ifelse和循环。这是一个基本的R解决方案:

对于matComp的每一行,您希望找到列名称包含给定“后缀”(x或y)的正确值Level的列,并将该值分配给新的refdat列。您可以使用match函数执行此操作。

在下面的代码中,我们使用apply遍历matComp的每一行。在每一行中,我们使用match查找所需列的索引,以便我们可以返回refdat的正确值。 sapply遍历两个后缀,cbind将两个新列添加到matcomp

matComp = cbind(matComp, 
                sapply(paste0("refdat_",c("x","y")), function(var) {
                  suffix = substr(var, nchar(var), nchar(var))
                  apply(matComp, 1, function(vec) {
                    vec[match(paste0("v", vec["Level"], "_", suffix), names(vec))]
                  })
                }), stringsAsFactors=FALSE)
  Level v5_x v5_y v6_x v6_y v7_x v7_y refdat_x refdat_y
1     5    x    e    m    t    k    z        x        e
2     6    z    d    r    e    a    l        r        e
3     6    p    n    x    z    j    x        x        z
4     7    o    g    i    c    u    d        u        d
5     5    b    s    y    u    h    o        b        s

答案 1 :(得分:0)

好吧,我现在意识到哈德利已经为最佳解决方案做好了准备;我需要批量处理列转换。我收集具有相同问题(过滤器)的所有列,解决问题,然后以拆分,应用,组合方法将所有帧重新连接在一起。

效率更高:将问题解决为3个表而不是数百个柱状迭代测试每个数据点然后连续响应。

library(magrittr)

matComp %<>% add_rownames
v5Mat <- matComp %>% filter(Level == 5) %>% select(rowname, starts_with("v5"))
v6Mat <- matComp %>% filter(Level == 6) %>% select(rowname, starts_with("v6"))
v7Mat <- matComp %>% filter(Level == 7) %>% select(rowname, starts_with("v7"))
colnames(v5Mat) %<>%  gsub("v\\d_", "ref", .)
colnames(v6Mat) %<>%  gsub("v\\d_", "ref", .)
colnames(v7Mat) %<>%  gsub("v\\d_", "ref", .)
refinedMat <- 
    Reduce(function(...) merge(..., all=TRUE), list(matComp, v5Mat, v6Mat, v7Mat)) %>% 
    group_by(rowname) %>% 
    summarise_each(funs(na.omit))
refinedMat

结果:

 Source: local data frame [5 x 10]

   rowname  refx  refy Level  v5_x  v5_y  v6_x  v6_y  v7_x  v7_y
     (chr) (chr) (chr) (int) (chr) (chr) (chr) (chr) (chr) (chr)
 1       1     x     e     5     x     e     m     t     k     z
 2       2     r     e     6     z     d     r     e     a     l
 3       3     x     z     6     p     n     x     z     j     x
 4       4     u     d     7     o     g     i     c     u     d
 5       5     b     s     5     b     s     y     u     h     o