如果不同,则用字符串将列分开

时间:2019-05-29 15:48:39

标签: r dplyr tidyr

我有一个数据框,如果它们包含不同的字符串或单词,我想拆分它们的列。

我正在尝试使用R中的其他方法,但无法正常工作

我的数据框如下:

df <- data.frame(x = c(NA, "TAP1", "TAP1", "TAP2"), y = c("TAP1", "TAP2", "TAP2", "TAP3" ))

例如,我正在尝试第一列:

df <- data.frame(x = c(NA, "TAP1", "TAP1", "TAP2"))
df %>% separate(x, c("TAP1", "TAP2"), extra = "drop", fill = "right")

但不起作用

我有下一个输出:

TAP1 TAP2
1 <NA> <NA>
2 TAP1 <NA>
3 TAP1 <NA>
4 TAP2 <NA>

我的预期输出是:

 TAP1 TAP2
1 <NA> <NA>
2 TAP1 <NA>
3 TAP1 <NA>
4 <NA> TAP2

我想对完整数据框中的所有列执行相同的操作,在这些列中我有不同的单词组合,例如TAP1,TAP2,TAP3 ...等。

在此示例中,考虑到x和y列的最终表将是。

 df <- data.frame(x = c(NA, "TAP1", "TAP1", "TAP2"), y = c("TAP1", "TAP2",   "TAP2", "TAP3" ))

  TAP1 TAP2 TAP1.1 TAP2.2 TAP3.3
1 <NA> <NA> TAP1   <NA>   <NA>
2 TAP1 <NA> <NA>   TAP2   <NA>
3 TAP1 <NA> <NA>   TAP2   <NA>
4 <NA> TAP2 <NA>   <NA>   TAP3

3 个答案:

答案 0 :(得分:3)

我们可以使用spread

library(tidyverse)
df %>% 
   mutate(n = row_number()) %>% 
   group_by(x) %>% 
   mutate(rn = row_number(), y = x) %>%
   spread(y, x) %>% 
   select(TAP1, TAP2)
# A tibble: 4 x 2
#  TAP1  TAP2 
#  <fct> <fct>
#1 <NA>  <NA> 
#2 TAP1  <NA> 
#3 TAP1  <NA> 
#4 <NA>  TAP2 

通过多列,我们可以gatherspread

rownames_to_column(df, 'rn') %>%
   gather(key, val, -rn) %>%
   mutate(val1 = val) %>% 
   unite(val, val,key) %>% 
   group_by(val) %>%    # not really need for this example
   mutate(ind = row_number()) %>% # not needed here though
   spread(val, val1) %>%
   select(starts_with("TAP"))
# A tibble: 4 x 5
# TAP1_x TAP1_y TAP2_x TAP2_y TAP3_y
#  <chr>  <chr>  <chr>  <chr>  <chr> 
#1 <NA>   TAP1   <NA>   <NA>   <NA>  
#2 TAP1   <NA>   <NA>   TAP2   <NA>  
#3 TAP1   <NA>   <NA>   TAP2   <NA>  
#4 <NA>   <NA>   TAP2   <NA>   TAP3  

答案 1 :(得分:1)

这是一个基本解决方案。这会遍历您列中的所有可能因素(即TAP1TAP2)并检查它们的行踪。对于存在它们的地方,它将返回级别的名称。对于不存在的地方,它将返回NA。然后,我将结果列表重新打包到数据框中,并重命名列。

# Original data frame
df <- data.frame(x = c(NA, "TAP1", "TAP1", "TAP2"))

# Repackage
df2 <- data.frame(lapply(levels(df$x), function(x)ifelse(df$x == x, x, NA)))

# Fix names
names(df2) <- levels(df$x)

# Check results
df2
#>   TAP1 TAP2
#> 1 <NA> <NA>
#> 2 TAP1 <NA>
#> 3 TAP1 <NA>
#> 4 <NA> TAP2

reprex package(v0.3.0)于2019-05-29创建


根据您的更新:

# Original data frame
df <- data.frame(x = c(NA, "TAP1", "TAP1", "TAP2"), 
                 y = c("TAP1", "TAP2",   "TAP2", "TAP3" ))

# Define splitter function
splitter <- function(foo){
  tmp <- data.frame(lapply(levels(foo), function(x)ifelse(foo == x, x, NA)))
  names(tmp) <- levels(foo)
  tmp
}

# Run over data frame and bind together
do.call(cbind, lapply(df, splitter))
#>   x.TAP1 x.TAP2 y.TAP1 y.TAP2 y.TAP3
#> 1   <NA>   <NA>   TAP1   <NA>   <NA>
#> 2   TAP1   <NA>   <NA>   TAP2   <NA>
#> 3   TAP1   <NA>   <NA>   TAP2   <NA>
#> 4   <NA>   TAP2   <NA>   <NA>   TAP3

reprex package(v0.3.0)于2019-05-29创建

与以前的原理相同,但是我定义了一个应用于每列的函数,并且使用do.callcbind将结果绑定在一起。

答案 2 :(得分:1)

使用tidyversedummies软件包的解决方案。 df3是最终输出。

library(tidyverse)
library(dummies)

df2 <- dummy.data.frame(df) %>% select(-ends_with("NA"))

cols <- str_remove(names(df2), regex("^x|^y"))

df3 <- modify2(df2, cols, ~ifelse(.x == 0, NA, .y))

df3
#   xTAP1 xTAP2 yTAP1 yTAP2 yTAP3
# 1  <NA>  <NA>  TAP1  <NA>  <NA>
# 2  TAP1  <NA>  <NA>  TAP2  <NA>
# 3  TAP1  <NA>  <NA>  TAP2  <NA>
# 4  <NA>  TAP2  <NA>  <NA>  TAP3