【问题标题】:R Multiple Columns by Delimiter in each Column, Match String to ValueR多列按每列中的分隔符,将字符串与值匹配
【发布时间】:2017-08-09 05:15:22
【问题描述】:

很抱歉这个菜鸟问题,但几天后我无法弄清楚如何做到这一点。我一直在尝试使用R。简单来说,我有两列如下

A:B:C:D:F | 1.1:2.1:3.1:4.1:6.1
A:B:D:F | 1.2:2.2:4.2:6.2
A:B:C:F | 1.3:2.3:3.3:6.3
B:C:D:F | 2.4:3.4:4.4:6.4

注意分隔符是':'。最后我想要这个:

A   | B | C | D | E | F
1.1 | 2.1   | 3.1 | 4.1 | NA | 6.1
1.2 | 2.2 | NA  | 4.2   | NA    | 6.2
1.3 | 2.3   | 3.3   | NA    | NA    | 6.3
NA  | 2.4   | 3.4   | 4.4   | NA    | 6.4

为什么我不能解决:

  • 第二列中的值对于每一行都不同,所以我需要循环检查第 1 列第 x 行是否有字符串,如果存在则将数字插入相应的第 2 列第 x 行。 **我刚刚为行选择了 1.1、1.2 等,以便于概念化。

  • 0 或 NA 不包含在第 1 列中,因此当缺少值时,我需要跳过列,例如在玩具示例中,第 2 行缺少 C 和 E 建议列。每行没有所需数量的字符串和对应的值(第 1 行有 5 个字符串,第 2 到第 4 行有 4 个

我会想象类似于以下内容的内容,将“1”替换为相应的第 2 列、第 x 行值,但我不知道该怎么做。我尝试过但被困在插入第 2 列值的另一种方法是仅根据是否存在字符串来创建具有 1 和 0 的列,这就是我遇到代码 sn-p 的方式。

df$A <- ifelse(grepl("A", df$PASS, ignore.case = T), "1", "0")

很抱歉写了这么长的文章,但我被卡住了。我觉得这超出了我的初级 R 水平。向任何能够解决这个问题的人致敬!

【问题讨论】:

  • 你说的那两列在哪里?还是你的意思是四行??
  • 你从哪里得到E???

标签: r string split delimiter na


【解决方案1】:

这是一个基于 R 的解决方案,没有 tidyverse 的魔力。它假设您可以将所有数据作为一个大字符串读取,但为输入流更改它并不难。

x <- "A:B:C:D:F | 1.1:2.1:3.1:4.1:6.1
A:B:D:F | 1.2:2.2:4.2:6.2
A:B:C:F | 1.3:2.3:3.3:6.3
B:C:D:F | 2.4:3.4:4.4:6.4"

data <- unlist(str_split(x, "\n"))
result <- matrix(as.numeric(NA), nrow = length(data), ncol = 6)
colnames(result) <- c("A", "B", "C", "D", "E", "F")

for (i in 1:length(data)) {
    split_data <- unlist(str_split(data[i], " [|] "))
    print(split_data)
    indices <- unlist(str_split(split_data[1], ":"))
    values <- unlist(str_split(split_data[2], ":"))

    for (j in 1:length(indices)) {
        result[i, indices[j]] <- as.numeric(values[j])
    }
}

result

【讨论】:

    【解决方案2】:

    我们可以试试tidyverse

    library(tidyverse)
    res <- df1 %>%
            map(~strsplit(., ":")) %>% 
            transpose %>% 
            map(~set_names(as.data.frame.list(as.numeric(.[[2]])), .[[1]]))  %>% 
            bind_rows %>%
            right_join(as.data.frame(setNames(rep(list(NA), 6), LETTERS[1:6])), .) 
    
    res
    #    A   B   C   D  E   F
    #1 1.1 2.1 3.1 4.1 NA 6.1
    #2 1.2 2.2  NA 4.2 NA 6.2
    #3 1.3 2.3 3.3  NA NA 6.3
    #4  NA 2.4 3.4 4.4 NA 6.4
    

    数据

    df1 <- structure(list(col1 = c("A:B:C:D:F", "A:B:D:F", "A:B:C:F", "B:C:D:F"
     ), col2 = c("1.1:2.1:3.1:4.1:6.1", "1.2:2.2:4.2:6.2", "1.3:2.3:3.3:6.3", 
     "2.4:3.4:4.4:6.4")), .Names = c("col1", "col2"), class = "data.frame", 
     row.names = c(NA, -4L))
    

    【讨论】:

      【解决方案3】:

      使用基础 R 并以通用格式编写:

      使用数据

       df1 <- structure(list(col1 = c("A:B:C:D:F", "A:B:D:F", "A:B:C:F", "B:C:D:F"), col2 = c
      ("1.1:2.1:3.1:4.1:6.1", "1.2:2.2:4.2:6.2", "1.3:2.3:3.3:6.3", "2.4:3.4:4.4:6.4")),
      .Names = c("col1", "col2"), class = "data.frame",  row.names = c(NA, -4L))
      

      那么代码就是

      a=apply(df1,1,strsplit,":",fixed=TRUE)
      b=lapply(a,function(x){y=`names<-`(as.numeric(x[[2]]),x[[1]]);data.frame(t(y))})
      d=Reduce(function(x,y) merge(x,y,by =intersect(names(x),names(y)),all.x = TRUE,all.y = TRUE),b)
      b1=max(match(names(unlist(b)),LETTERS))
      e=LETTERS[1:b1][!LETTERS[1:b1]%in%names(d)]
      f=`names<-`(data.frame(d,rep(list(NA),length(e))),c(names(d),e))
      g=f[,order(names(f))]
      Reduce(rbind,c(paste0(names(g),collapse = " | "),apply(g,1,paste0,collapse="|")))
      

      如果数据是

       x <- "A:B:C:D:F | 1.1:2.1:3.1:4.1:6.1
             A:B:D:F | 1.2:2.2:4.2:6.2 
             A:B:C:F | 1.3:2.3:3.3:6.3
             B:C:D:F | 2.4:3.4:4.4:6.4"
      

      那么你只需要用下面的一行代码转换一下,然后运行上面的代码。

       df1=matrix(unlist(strsplit(unlist(strsplit(x,"\n"))," | ",fixed = T)),ncol=2,byrow=T)
      

      【讨论】:

        【解决方案4】:

        我建议查看我的“splitstackshape”包中的cSplit 和dcast 的组合:

        library(splitstackshape)
        dcast(cSplit(as.data.table(df1)[, id := 1:nrow(df1)], names(df1), ":", "long"), 
              id ~ col1, value.var = "col2")
           id   A   B   C   D   F
        1:  1 1.1 2.1 3.1 4.1 6.1
        2:  2 1.2 2.2  NA 4.2 6.2
        3:  3 1.3 2.3 3.3  NA 6.3
        4:  4  NA 2.4 3.4 4.4 6.4
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2023-03-12
          • 2020-05-02
          • 2020-07-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多