对列进行突变,以使基名称排列在一起

时间:2019-06-13 21:06:59

标签: r dplyr tidyr purrr tibble

假设我有一个由"/"分割并已放入数据帧的文件路径向量。这些文件路径具有不同的长度,但是到了一天结束时,我希望所有基本名称都在同一列中排列。我在下面提供了我的意思和所需输出的示例。

library(tidyverse)

dat <- tibble(
    V1 = rep("run1", 5),
    V2 = rep("ox", 5),
    V3 = c("performance.csv", "analysis", "analysis", "performance.csv", "analysis"),
    V4 = c("", "rod1", "rod2", "rod3", "performance.csv"), 
    V5 = c("", "performance.csv", "performance.csv", "performance.csv", "")
)

dat
#> # A tibble: 5 x 5
#>   V1    V2    V3              V4              V5             
#>   <chr> <chr> <chr>           <chr>           <chr>          
#> 1 run1  ox    performance.csv ""              ""             
#> 2 run1  ox    analysis        rod1            performance.csv
#> 3 run1  ox    analysis        rod2            performance.csv
#> 4 run1  ox    performance.csv rod3            performance.csv
#> 5 run1  ox    analysis        performance.csv ""

output <- tibble(
    V1 = rep("run1", 5),
    V2 = rep("ox", 5),
    V3 = c("", "analysis", "analysis", "", "analysis"),
    V4 = c("", "rod1", "rod1", "rod2", ""), 
    V5 = c("performance.csv", "performance.csv", "performance.csv", "performance.csv", "performance.csv")
)

output
#> # A tibble: 5 x 5
#>   V1    V2    V3       V4    V5             
#>   <chr> <chr> <chr>    <chr> <chr>          
#> 1 run1  ox    ""       ""    performance.csv
#> 2 run1  ox    analysis rod1  performance.csv
#> 3 run1  ox    analysis rod1  performance.csv
#> 4 run1  ox    ""       rod2  performance.csv
#> 5 run1  ox    analysis ""    performance.csv

我的想法是求助于for循环,在该循环中,我检查一列是否包含基本名称,如果包含,则将其替换为""并将其移至最后一列。我在形成这种逻辑时遇到困难,并且知道必须有一种更好的方法来利用tidyverse。

3 个答案:

答案 0 :(得分:6)

创建一个函数rearrange,该函数重新排列行,将基名放在最后,如果它的末尾还没有,则将其原始位置清空。我们假定任何带点的条目都是基本名称。然后将rearrange应用于每一行。

rearrange <- function(x) {
  i <- grep(".", x, fixed = TRUE)[1]
  x[length(x)] <- x[i]
  if (i < length(x)) x[i] <- ""
  x
}
as_tibble(t(apply(dat, 1, rearrange)))

给予:

# A tibble: 5 x 5
  V1    V2    V3       V4    V5             
  <chr> <chr> <chr>    <chr> <chr>          
1 run1  ox    ""       ""    performance.csv
2 run1  ox    analysis rod1  performance.csv
3 run1  ox    analysis rod2  performance.csv
4 run1  ox    ""       rod3  performance.csv
5 run1  ox    analysis ""    performance.csv

答案 1 :(得分:1)

这是一种tidyverse的方式-

dat %>% 
  rownames_to_column("id") %>% 
  gather(key, variable, -id) %>% 
  group_by(id) %>% 
  mutate(
    variable = case_when(
      key == "V5" ~ tail(grep(".csv", x = variable, value = T), 1),
      key != "V5" & grepl(".csv", x = variable) ~ "",
      TRUE ~ variable
    )
  ) %>% 
  ungroup() %>% 
  spread(key, variable)


# A tibble: 5 x 6
  id    V1    V2    V3       V4    V5             
  <chr> <chr> <chr> <chr>    <chr> <chr>          
1 1     run1  ox    ""       ""    performance.csv
2 2     run1  ox    analysis rod1  performance.csv
3 3     run1  ox    analysis rod2  performance.csv
4 4     run1  ox    ""       rod3  performance.csv
5 5     run1  ox    analysis ""    performance.csv

答案 2 :(得分:1)

一个base R使用max.col的选项。获取数据集的子集的列索引(第3列至第5列),其中.作为元素,cbind与行索引(seq_len(nrow(dat))),根据以下内容从数据集中提取元素:这些索引并将其分配给“ V5”。然后根据逻辑矩阵(do.call(cbind, .)的TRUE值将第三列和第四列更改为空白(""

dat <- as.data.frame(dat)
lst1 <- lapply(dat[3:5], grepl, pattern = '\\.')
ij <- cbind(seq_len(nrow(dat)), max.col(do.call(cbind, lst1), 'first'))
dat$V5 <-  dat[3:5][ij]
dat[3:4][do.call(cbind, lst1[1:2])] <- ""
dat
#    V1 V2       V3   V4              V5
#1 run1 ox               performance.csv
#2 run1 ox analysis rod1 performance.csv
#3 run1 ox analysis rod2 performance.csv
#4 run1 ox          rod3 performance.csv
#5 run1 ox analysis      performance.csv

或将tidyversecoalesce一起使用。在这里,我们将select列“ V3”到“ V5”遍历列(map),replace.csv以外的元素NAcoalesce将其绑定到单个列,将该列与原始数据集的子集列绑定,并将replace的第.列为空白的第{3}至第4列(""

library(tidyverse)
dat %>% 
  select(V3:V5) %>% 
  map_df(~ replace(.x, str_detect(.x, "\\.csv", negate = TRUE), NA)) %>% 
  transmute(V5 = coalesce(!!! .)) %>%
  bind_cols(dat %>% 
             select(-V5), .) %>% 
  mutate_at(vars(3:4), list(~ replace(., str_detect(., "\\."), '')))
# A tibble: 5 x 5
#  V1    V2    V3       V4    V5             
#  <chr> <chr> <chr>    <chr> <chr>          
#1 run1  ox    ""       ""    performance.csv
#2 run1  ox    analysis rod1  performance.csv
#3 run1  ox    analysis rod2  performance.csv
#4 run1  ox    ""       rod3  performance.csv
#5 run1  ox    analysis ""    performance.csv