我有一个看起来像这样的数据集
site <- c("A", "B", "C", "D", "E")
D01_1 <- c(1, 0, 0, 0, 1)
D01_2 <- c(1, 1, 0, 1, 1)
D02_1 <- c(1, 0, 1, 0, 1)
D02_2 <- c(0, 1, 0, 0, 1)
D03_1 <- c(1, 1, 0, 0, 0)
D03_2 <- c(0, 1, 0, 0, 1)
df <- data.frame(site, D01_1, D01_2, D02_1, D02_2, D03_1, D03_2)
我正在尝试联合D0x_1
和D0x_2
列,以便列中的值以斜杠分隔。我可以使用以下代码执行此操作,它可以正常工作:
library(dplyr)
library(tidyr)
df.unite <- df %>%
unite(D01, D01_1, D01_2, sep = "/", remove = TRUE) %>%
unite(D02, D02_1, D02_2, sep = "/", remove = TRUE) %>%
unite(D03, D03_1, D03_2, sep = "/", remove = TRUE)
...但问题是它要求我多次输入每个unite
对,并且在我的数据集中的大量列中它很难处理。在dplyr
中是否有一种方法可以在相似的图案列名中联合,然后在列中循环? unite_each
似乎不存在。
答案 0 :(得分:4)
两个选项,实际上是重新排列的相同内容。
首先,您可以使用lapply
以编程方式跨列应用unite_
(可以传递字符串的标准评估版)。为此,您需要构建一个名称列表供其使用,然后将lapply
包裹在do.call(cbind
中以捕获列,cbind
{{1}回到它。总而言之:
site
或者,如果你真的喜欢管道,你实际上可以把整个东西整理成一个链(cols <- unique(substr(names(df)[-1], 1, 3))
cbind(site = df$site, do.call(cbind,
lapply(cols, function(x){unite_(df, x, grep(x, names(df), value = TRUE),
sep = '/', remove = TRUE) %>% select_(x)})
))
# site D01 D02 D03
# 1 A 1/1 1/0 1/0
# 2 B 0/1 0/1 1/1
# 3 C 0/0 1/0 0/0
# 4 D 0/1 0/0 0/0
# 5 E 1/1 1/1 0/1
包含!),换掉lapply
个的一些基本函数:
dplyr
查看中间产品以了解它是如何组合在一起的,但它与基本方法的逻辑基本相同。
答案 1 :(得分:3)
这是一个具有基本功能的解决方案。首先,我在列中查找*** _ 1的索引。我还使用gsub()
和unique()
为最终流程的列创建了名称。 sapply部分使用/
粘贴两列。如果x = 1,则x + 1 = 2.因此,您始终选择彼此相邻的两列并处理粘贴作业。然后,我添加了site
cbind()
并创建了一个数据框。最后一项工作是分配列名。
library(magrittr)
ind <- grep(pattern = "1$", x = names(df))
names <- unique(gsub(pattern = "_\\d+$",
replacement = "", x = names(df)))
sapply(ind, function(x){
foo <- paste(df[,x], df[, x+1], sep = "/")
foo
}) %>%
cbind(as.character(df$site), .) %>%
data.frame -> out
names(out) <- names
# site D01 D02 D03
#1 A 1/1 1/0 1/0
#2 B 0/1 0/1 1/1
#3 C 0/0 1/0 0/0
#4 D 0/1 0/0 0/0
#5 E 1/1 1/1 0/1
答案 2 :(得分:0)
您也可以使用简单的基础R方法:
cols <- split(names(df)[-1], sub("_\\d+", "", names(df)[-1]))
cbind(df[1], sapply(names(cols), function(col) {
do.call(paste, c(df[cols[[col]]], sep = "/"))
}))
# site D01 D02 D03
#1 A 1/1 1/0 1/0
#2 B 0/1 0/1 1/1
#3 C 0/0 1/0 0/0
#4 D 0/1 0/0 0/0
#5 E 1/1 1/1 0/1