在R中拆分字符串并逐列重新进行重新计算

时间:2019-03-07 10:26:49

标签: r string

我在R中有一个复杂的字符串拆分问题。在我的数据框中,我有一列包含不同长度的字符串。

   Site  Class
   A1    D2.13
   A2     E1.4
   A3     FA.1
   A4    H2.14
   A5        F
   AR       G1

现在,我想添加新的列,以按字符重新组合字符串,而应逐字符“忽略”点。

   Site Class1 Class2 Class3 Class4
   A1      D     D2   D2.1  D2.13
   A2      E     E1   E1.4     NA
   A3      F     FA   FA.1     NA
   A4      H     H2   H2.1  H2.14
   A5      F     NA     NA     NA
   AR      G     G1     NA     NA

测试数据:

structure(list(Site = c("A1", "A2", "A3", "A4", "A5", "AR"), 
           Class = c("D2.13", "E1.4", "FA.1", "H2.14", "F","G1")), 
           class = "data.frame", row.names = c(NA, -6L)) 

3 个答案:

答案 0 :(得分:2)

一个想法是将Class按每个字符进行拆分,然后将Reduceaccumulate = TRUE一起使用,以便将它们一个个地粘贴回去。然后,我们将其长度设置为最大长度rbindcbind回到原始数据帧,即

l1 <- lapply(strsplit(as.character(df$Class), ''), function(i){i1 <- Reduce(paste0, i, accumulate = TRUE); 
                                                               i1 <- i1[!grepl('\\.$', i1)]; 
                                                               i1})
final_list <- lapply(l1, `length<-`, max(lengths(l1)))
cbind.data.frame(df$Site, do.call(rbind, final_list))

给出,

  df$Site 1    2    3     4
1      A1 D   D2 D2.1 D2.13
2      A2 E   E1 E1.4  <NA>
3      A3 F   FA FA.1  <NA>
4      A4 H   H2 H2.1 H2.14
5      A5 F <NA> <NA>  <NA>
6      AR G   G1 <NA>  <NA>

您可以照常整理列名

答案 1 :(得分:0)

使用dplyr

轻松
df%>%rowwise()%>%mutate(Class1=substr(Class,1,1),
                        Class2=ifelse(nchar(strsplit(Class,"\\.")[[1]][1])==2,substr(Class,1,2),NA),
                        Class3=ifelse(nchar(strsplit(Class,"\\.")[[1]][2])>0,substr(Class,1,4),NA),
                        Class4=ifelse(nchar(Class)>4,Class,NA)
                        )

Source: local data frame [6 x 6]
Groups: <by row>

# A tibble: 6 x 6
  Site  Class Class1 Class2 Class3 Class4
  <chr> <chr> <chr>  <chr>  <chr>  <chr> 
1 A1    D2.13 D      D2     D2.1   D2.13 
2 A2    E1.4  E      E1     E1.4   NA    
3 A3    FA.1  F      FA     FA.1   NA    
4 A4    H2.14 H      H2     H2.1   H2.14 
5 A5    F     F      NA     NA     NA    
6 AR    G1    G      G1     NA     NA 

答案 2 :(得分:0)

与@Sotos所做的类似的想法(关键部分是Reducestrsplit),但配置有所不同:

library(data.table)

df <- setDT(df)[, .(Class = Reduce(paste0, unlist(strsplit(as.character(Class), split = "")), accumulate = T)), 
                by = Site][
                  !grepl("\\.$", Class)][, nr := paste0("Class", rleid(Class)), by = Site]

dcast(df, Site ~ nr, value.var = "Class")

输出:

   Site Class1 Class2 Class3 Class4
1:   A1      D     D2   D2.1  D2.13
2:   A2      E     E1   E1.4   <NA>
3:   A3      F     FA   FA.1   <NA>
4:   A4      H     H2   H2.1  H2.14
5:   A5      F   <NA>   <NA>   <NA>
6:   AR      G     G1   <NA>   <NA>