【问题标题】:Splitting columns in R在 R 中拆分列
【发布时间】:2014-03-07 14:50:23
【问题描述】:

我是 R 新手,我有一个包含 17 列和超过 1m 行的大型数据集。我想通过分隔符“/”将其中一列分成 4 列。 R 需要很长时间才能完成以下命令。有没有更好的方法来完成以下。我已经提供了尽可能多的代码信息,如果有任何帮助,我将不胜感激。

sample2 <- read.csv("week1.csv", header=TRUE)
summ1 <- subset(sample2,select= -c(3,7), subset =(SPORTS_ID =='1'))
summ1 <- summ1[,-c(1)]
library(splitstackshape)
summ2 <- concat.split.multiple(summ1,2 , "/")
summ2 <- summ2[,-c(1,15)]
summ3 <- concat.split.multiple(summ2,14, "v")
write.csv(summm3, file="test.csv")

【问题讨论】:

  • 抱歉,应该读取其中一列而不是我要拆分的行
  • 如果没有一些示例数据,将很难提供帮助。
  • 另外,如果数据是平衡的,你可能想放弃基本的concat.split.multiple 方法并尝试我在这里进行的重写:gist.github.com/mrdwab/6873058

标签: r splitstackshape


【解决方案1】:

你可以使用strsplit:

dat <- data.frame(a = c("a/b/c/d",
                        "e/f/g/h"),
                  stringsAsFactors = FALSE)
#         a
# 1 a/b/c/d
# 2 e/f/g/h

cbind(dat, do.call(rbind, strsplit(dat$a, "/")))
#         a 1 2 3 4
# 1 a/b/c/d a b c d
# 2 e/f/g/h e f g h

【讨论】:

  • +1。为了提高效率,我会在您的strsplit 中添加一个fixed = TRUE。这在the benchmarks I've posted 中的表现相当不错。
【解决方案2】:

正如我在评论中提到的,如果您的数据是平衡的(也就是说,您希望在拆分数据后得到一个漂亮的矩形数据集),您应该查看我的 concat.split.DT 函数。

这里有一些测试。

Sven 的数据,但有 20K 行而不是 2 行

dat <- do.call(rbind, replicate(1e4, dat, simplify=FALSE))
dim(dat)
# [1] 20000     1

“stringr”函数可能有点慢:

library(stringr)
system.time(do.call(rbind, str_split(dat$a,  "/")))
#    user  system elapsed 
#   3.194   0.000   3.211 

但其他解决方案的表现如何?

fun1 <- function() concat.split.multiple(dat, "a", "/")
fun2 <- function() do.call(rbind, strsplit(dat$a, "/", fixed=TRUE))
## ^^ fixed = TRUE will make a big difference
fun3 <- function() concat.split.DT(dat, "a", "/")

library(microbenchmark)
microbenchmark(fun1(), fun2(), fun3(), times = 10)
# Unit: milliseconds
#    expr       min        lq    median        uq       max neval
#  fun1() 530.46597 534.13486 535.19139 538.91488 553.61919    10
#  fun2()  30.22265  31.07287  31.81474  32.93936  40.28859    10
#  fun3()  22.57517  22.94169  23.10297  23.30907  31.97640    10

所以,对于普通的 concat.split.multiple(它只在底层使用 read.table)大约需要半秒,而对于 strsplitconcat.split.DT(后者使用 fread 来自引擎盖下的“data.table”)。

让我们进一步扩大规模,现在达到 100 万行...

dat <- do.call(rbind, replicate(50, dat, simplify=FALSE))
dim(dat)
# [1] 1000000       1

microbenchmark(fun2(), fun3(), times = 5)
# Unit: seconds
#    expr      min       lq    median        uq       max neval
#  fun2() 6.257892 6.522199 13.728283 13.934860 14.277432     5
#  fun3() 1.671739 1.830485  2.203076  2.470872  2.572917     5

concat.split.DT 方法的优点是使用简单的语法可以方便地拆分多个列:

dat2 <- do.call(cbind, replicate(5, dat, simplify = FALSE))
dim(dat2)
# [1] 1000000       5
names(dat2) <- make.unique(names(dat2))
head(dat2)
#         a     a.1     a.2     a.3     a.4
# 1 a/b/c/d a/b/c/d a/b/c/d a/b/c/d a/b/c/d
# 2 e/f/g/h e/f/g/h e/f/g/h e/f/g/h e/f/g/h
# 3 a/b/c/d a/b/c/d a/b/c/d a/b/c/d a/b/c/d
# 4 e/f/g/h e/f/g/h e/f/g/h e/f/g/h e/f/g/h
# 5 a/b/c/d a/b/c/d a/b/c/d a/b/c/d a/b/c/d
# 6 e/f/g/h e/f/g/h e/f/g/h e/f/g/h e/f/g/h

现在,让我们一次将它们全部拆分:

system.time(out <- concat.split.DT(dat2, names(dat2), "/"))
#    user  system elapsed 
#   6.260   0.040   6.532 
out
#          a_1 a_2 a_3 a_4 a.1_1 a.1_2 a.1_3 a.1_4 a.2_1 a.2_2 a.2_3 a.2_4 a.3_1
#       1:   a   b   c   d     a     b     c     d     a     b     c     d     a
#       2:   e   f   g   h     e     f     g     h     e     f     g     h     e
#       3:   a   b   c   d     a     b     c     d     a     b     c     d     a
#       4:   e   f   g   h     e     f     g     h     e     f     g     h     e
#       5:   a   b   c   d     a     b     c     d     a     b     c     d     a
#      ---                                                                      
#  999996:   e   f   g   h     e     f     g     h     e     f     g     h     e
#  999997:   a   b   c   d     a     b     c     d     a     b     c     d     a
#  999998:   e   f   g   h     e     f     g     h     e     f     g     h     e
#  999999:   a   b   c   d     a     b     c     d     a     b     c     d     a
# 1000000:   e   f   g   h     e     f     g     h     e     f     g     h     e
#          a.3_2 a.3_3 a.3_4 a.4_1 a.4_2 a.4_3 a.4_4
#       1:     b     c     d     a     b     c     d
#       2:     f     g     h     e     f     g     h
#       3:     b     c     d     a     b     c     d
#       4:     f     g     h     e     f     g     h
#       5:     b     c     d     a     b     c     d
#      ---                                          
#  999996:     f     g     h     e     f     g     h
#  999997:     b     c     d     a     b     c     d
#  999998:     f     g     h     e     f     g     h
#  999999:     b     c     d     a     b     c     d
# 1000000:     f     g     h     e     f     g     h

【讨论】:

    【解决方案3】:

    这应该可以帮助您入门。您可能需要根据数据包含的内容调整正则表达式模式。一个可重复的例子会有所帮助。 How to make a great R reproducible example?

    library(stringr)
    df <- as.data.frame(cbind(x = seq(1,10,1), y = rep("first/second", 10)), stringsAsFactors = FALSE)
    df
    df$first <- str_replace(df$y, "\\/\\w+", "")
    df$second <- str_replace(df$y, "\\w+\\/", "")
    df
    
    > df
        x            y first second
    1   1 first/second first second
    2   2 first/second first second
    3   3 first/second first second
    4   4 first/second first second
    5   5 first/second first second
    6   6 first/second first second
    7   7 first/second first second
    8   8 first/second first second
    9   9 first/second first second
    10 10 first/second first second
    

    【讨论】:

    • 抱歉,由于某些原因,这将是一个非常糟糕的主意。首先,如果您希望拆分的结果有 20 列,您是否打算这样做?
    • 原始问题指出,预计有四个新列。您还有什么其他顾虑?
    • 另一个问题是“stringr”不一定会给你任何速度提升。更不用说关于 SO 的一个好的答案不一定是解决问题中所述的直接问题的答案,而是可能提出适用于更广泛情况的解决方案的答案。
    • 大家好,感谢所有的回复,我会在一段时间内尝试这些。数据列的副本如下,我将拆分为 4 个新列 = 英格兰足球/巴克莱超级联赛/8 月 18 日的赛程/阿森纳对桑德兰
    • 我想将上述内容分解为 English Soccer,例如在列标题 League 下的一列中,在 Comp 下的 Barclays Premier League 下一列中
    【解决方案4】:

    如果您要处理字符并且不介意列表,stringr 包中的 str_split 应该会有所帮助

    library(stringr)
    x <- 'hello/hi/hey/hola'
    str_split(x)
    [[1]]
    [1] "hello" "hi" "hey" "hola" 
    

    【讨论】:

    • 我猜测 (and was able to verify) 这种方法效率不高。使用 base R 的字符串操作工具会更有效率。
    猜你喜欢
    • 2016-11-10
    • 2022-11-21
    • 2018-09-19
    • 2020-03-26
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多