遍历dplyr中的列
我试图通过数据库的列逐步迭代函数。有哪些选项可供选择?我是否仅限于for循环,或者是否可以使用dplyr方法或类似的直观代码结构 本质上,我有一个比下面构造的矩阵大得多的矩阵,但具有相同的一般结构。第一列解释了选择哪个版本作为优化数据收集,然后解释了组成这三个版本的所有数据遍历dplyr中的列,r,dplyr,R,Dplyr,我试图通过数据库的列逐步迭代函数。有哪些选项可供选择?我是否仅限于for循环,或者是否可以使用dplyr方法或类似的直观代码结构 本质上,我有一个比下面构造的矩阵大得多的矩阵,但具有相同的一般结构。第一列解释了选择哪个版本作为优化数据收集,然后解释了组成这三个版本的所有数据 library(dplyr) # Function: creates a matrix of random strings, v = versionNumber matADv.maker <- function (v
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]
我想知道是否有一种简单的方法可以沿着数据帧传递函数
从本质上讲,我如何能够通过使用dplyr或类似的比for loops更简单的构造来迭代列?您可以利用列名的规律性来避免
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)
好吧,我现在意识到哈德利已经为最好的解决方案铺平了道路;我需要批量处理列转换。我收集具有相同问题(筛选器)的所有列,解决问题,然后以拆分、应用、合并方法将所有帧重新连接在一起 效率也更高:将问题处理为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
rowwise()
我不想总结一行中的所有数据,我需要完全改变一列(为该列中的每一行选择正确的数据),然后移到右边的下一行-将答案正确地改变到该行中的所有行-然后移到右边的下一行,等等。有人在顶部钉了一个标志,指示我使用行迭代算法。我开始猜测的是,这种方法从来不是一次一列,而是在进入下一列之前按行排列;相反,数据总是一次在一行上处理:继续该行中的列到列,然后继续。我主要感兴趣的是找到一种方法来扩展dplyr的实用程序,从使用直接引用只对数据帧中的单个列进行变异,从而使我的代码能够修改数据帧中的多列部分;避免完全循环,并批量处理所有适当的列。仍在努力解决是否不可能出现我仍然需要列式迭代的情况,但至少在本例中,批量处理更好。同时还意识到我在代码中遗漏了matrix maker函数,因此示例无法完全复制。我把上面缺少的部分加进去了。太好了。非常聪明的方法!感谢您教会我match
作为逻辑开关替代品的功能。这看起来在很多情况下都会派上用场:期待着使用它。看看hadley关于tidy data的文章,我看到他指出了一个陷阱:“列标题是值,而不是变量名。”你在这里看到了这个陷阱。列名称后缀是实际数据,而不是变量名称。可能v
后面的数字本质上也是数据,而不是变量名。(我没有详细看你的问题,只是想了想你的第一段。)@Frank-谢谢你在tidyr中找到这一点。:-)这似乎确实是真的;然而,这似乎对我们有利。如果我们在colnames函数中提取名称,我们就可以像对待任何其他向量一样对待它们。@eipi10进一步扩展了这种转换,将实际列标题本身用作逻辑开关的直接信号。
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
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