将逗号分隔的单元格分隔为新行

时间:2011-02-09 18:35:24

标签: r

您好我有一个以逗号分隔的列的表,我需要将逗号分隔的值转换为新行。例如,给定的表是

Name     Start      End 
A        1,2,3    4,5,6
B          1,2      4,5
C      1,2,3,4  6,7,8,9   

我需要将其转换为

Name Start End
   A     1   4
   A     2   5  
   A     3   6
   B     1   4
   B     2   5 
   C     1   6
   C     2   7
   C     3   8   
   C     4   9

我可以使用VB脚本来做到这一点,但我需要使用R来解决它 任何人都可以解决这个问题吗?

4 个答案:

答案 0 :(得分:3)

您可能已在SO上提出此问题,因为没有处理统计信息的问题:)

无论如何,我编写了一个非常复杂和丑陋的解决方案,可能对你有用:

# load your data
x <- structure(list(Name = c("A", "B", "C"), Start = c("1,2,3", "1,2", 
"1,2,3,4"), End = c("4,5,6", "4,5", "6,7,8,9")), .Names = c("Name", 
"Start", "End"), row.names = c(NA, -3L), class = "data.frame")

在R中看起来像:

> x
  Name   Start     End length
1    A   1,2,3   4,5,6      3
2    B     1,2     4,5      2
3    C 1,2,3,4 6,7,8,9      4

借助strsplit来电进行数据转换:

data <- data.frame(cbind(
    rep(x$Name,as.numeric(lapply(strsplit(x$Start,","), length))),
    unlist(lapply(strsplit(x$Start,","), cbind)),
    unlist(lapply(strsplit(x$End,","), cbind))
    ))

命名新数据框:

names(data) <- c("Name", "Start", "End")

看起来像:

> data
  Name Start End
1    A     1   4
2    A     2   5
3    A     3   6
4    B     1   4
5    B     2   5
6    C     1   6
7    C     2   7
8    C     3   8
9    C     4   9

答案 1 :(得分:2)

这是一种适合您的方法。我假设你的三个输入向量在不同的对象中。我们将创建这些输入的列表并编写一个处理每个对象的函数,并以data.frame的形式返回它们与plyr。

这里需要注意的是将字符向量拆分为它的组成部分,然后使用as.numeric转换字符形式的数字。由于R按列填充矩阵,我们定义一个2列矩阵,让R为我们填充值。然后,我们检索“名称”列并将其全部放在data.frame中。 plyr非常适合处理列表并自动将其转换为data.frame

library(plyr)

a <- paste("A",1, 2,3,4,5,6, sep = ",", collapse = "")
b <- paste("B",1, 2,4,5, sep = ",", collapse = "")
c <- paste("C",1, 2,3,4,6,7,8,9, sep = ",", collapse = "")

input <- list(a,b,c)

splitter <- function(x) {
    x <- unlist(strsplit(x, ","))
    out <- data.frame(x[1], matrix(as.numeric(x[-1]), ncol = 2))
    colnames(out) <- c("Name", "Start", "End")
    return(out)
}


ldply(input, splitter)

输出:

> ldply(input, splitter)
 Name Start End
1    A     1   4
2    A     2   5
3    A     3   6
4    B     1   4
5    B     2   5
6    C     1   6
7    C     2   7
8    C     3   8
9    C     4   9

答案 2 :(得分:1)

separate_rows()中的tidyr函数是具有多个分隔值的观察的老大......

# create data 
library(tidyverse)
d <- data_frame(
  Name = c("A", "B", "C"), 
  Start = c("1,2,3", "1,2", "1,2,3,4"), 
  End = c("4,5,6", "4,5", "6,7,8,9")
)
d
# # A tibble: 3 x 3
#    Name   Start     End
#   <chr>   <chr>   <chr>
# 1     A   1,2,3   4,5,6
# 2     B     1,2     4,5
# 3     C 1,2,3,4 6,7,8,9

# tidy data
separate_rows(d, Start, End)
# # A tibble: 9 x 3
#    Name Start   End
#   <chr> <chr> <chr>
# 1     A     1     4
# 2     A     2     5
# 3     A     3     6
# 4     B     1     4
# 5     B     2     5
# 6     C     1     6
# 7     C     2     7
# 8     C     3     8
# 9     C     4     9

# use convert set to TRUE for integer column modes
separate_rows(d, Start, End, convert = TRUE)
# # A tibble: 9 x 3
#    Name Start   End
#   <chr> <int> <int>
# 1     A     1     4
# 2     A     2     5
# 3     A     3     6
# 4     B     1     4
# 5     B     2     5
# 6     C     1     6
# 7     C     2     7
# 8     C     3     8
# 9     C     4     9

答案 3 :(得分:0)

这是另一个,只是为了好玩。将d作为原始数据。

f <- function(x, ul = TRUE)
{
    x <- deparse(substitute(x))
    if(ul) unlist(strsplit(d[[x]], ','))
    else strsplit(d[[x]], ',')
}

> data.frame(Name = rep(d$Name, sapply(f(End, F), length)),
             Start = f(Start), End = f(End))
#   Name Start End
# 1    A     1   4
# 2    A     2   5
# 3    A     3   6
# 4    B     1   4
# 5    B     2   5
# 6    C     1   6
# 7    C     2   7
# 8    C     3   8
# 9    C     4   9