tidyr ::跨列模式联合

Ste*_*ven 7 r dplyr tidyr

我有一个看起来像这样的数据集

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)
Run Code Online (Sandbox Code Playgroud)

我试图统一D0x_1D0x_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)
Run Code Online (Sandbox Code Playgroud)

...但问题是它需要我unite多次输出每一对,并且在我的数据集中的大量列中它是不实用的.有没有办法在dplyr相似的图案列名称之间联合然后循环遍历列?unite_each似乎不存在.

ali*_*ire 5

两个选项,其实是同一个东西重新排列的。


选项 1. 嵌套调用

首先,您可以使用跨列以编程lapply方式应用unite_(您可以向其传递字符串的标准评估版本)。要做到这一点,你需要建立名字为它使用的列表,然后包裹lapplydo.call(cbind渔获列,cbind 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
Run Code Online (Sandbox Code Playgroud)

选项 2:链接

或者,如果你真的喜欢管道,你实际上可以把整个东西变成一个链(lapply包括!),换掉一些基本功能dplyr

df %>% select(-site) %>% names() %>% substr(1,3) %>% unique() %>%
  lapply(function(x){unite_(df, x, grep(x, names(df), value = TRUE), 
                            sep = '/', remove = TRUE) %>% select_(x)}) %>%
  bind_cols() %>% mutate(site = as.character(df$site)) %>% select(site, starts_with('D'))

# Source: local data frame [5 x 4]
# 
#    site   D01   D02   D03
#   (chr) (chr) (chr) (chr)
# 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
Run Code Online (Sandbox Code Playgroud)

查看中间产品以了解它们如何组合在一起,但它与基本方法的逻辑几乎相同。