【问题标题】:Insert a row of NAs after each group of data using data.table使用 data.table 在每组数据后插入一行 NA
【发布时间】:2015-01-01 11:34:15
【问题描述】:

我正在尝试在R 中的每组数据之后添加一行 NA。

之前有人问过类似的问题。 Insert a blank row after each group of data.

在这种情况下,接受的答案也可以正常工作,如下所示。

group <- c("a","b","b","c","c","c","d","d","d","d")
xvalue <- c(16:25)
yvalue <- c(1:10)
df <- data.frame(cbind(group,xvalue,yvalue))
df_new <- as.data.frame(lapply(df, as.character), stringsAsFactors = FALSE)
head(do.call(rbind, by(df_new, df$group, rbind, NA)), -1 )
     group xvalue yvalue
a.1      a     16      1
a.2   <NA>   <NA>   <NA>
b.2      b     17      2
b.3      b     18      3
b.31  <NA>   <NA>   <NA>
c.4      c     19      4
c.5      c     20      5
c.6      c     21      6
c.41  <NA>   <NA>   <NA>
d.7      d     22      7
d.8      d     23      8
d.9      d     24      9
d.10     d     25     10

对于大型 data.frame,我如何使用 data.table 加快速度?

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    你可以试试

    df$group <- as.character(df$group)
    setDT(df)[, .SD[1:(.N+1)], by=group][is.na(xvalue), group:=NA][!.N]
    #     group xvalue yvalue
    #1:     a     16      1
    #2:    NA     NA     NA
    #3:     b     17      2
    #4:     b     18      3
    #5:    NA     NA     NA
    #6:     c     19      4
    #7:     c     20      5
    #8:     c     21      6
    #9:    NA     NA     NA
    #10:    d     22      7
    #11:    d     23      8
    #12:    d     24      9
    #13:    d     25     10
    

    或者按照@David Arenburg 的建议

     setDT(df)[, indx := group][, .SD[1:(.N+1)], indx][,indx := NULL][!.N]
    

    或者

     setDT(df)[df[,.I[1:(.N+1)], group]$V1][!.N]
    

    或者可以根据@eddi的cmets进一步简化

     setDT(df)[df[, c(.I, NA), group]$V1][!.N]
    

    【讨论】:

    • 这是一个非常简洁的解决方案,尽管我认为您可以避免使用 group 并创建一些索引并将其留在那里(或之后将其删除),可能类似于 @987654326 @
    • 或者只是setDT(df)[, indx := group][, .SD[1:(.N+1)], indx][, indx := NULL][]
    • @DavidArenburg 我认为如果我使用.I,它可以变得更紧凑。
    • 最后一个解决方案很整洁
    • 我认为...df[, c(.I, NA), group]... 更容易阅读/理解
    【解决方案2】:

    我能想到的一种方法是先构造一个向量,如下所示:

    foo <- function(x) {
        o = order(rep.int(seq_along(x), 2L))
        c(x, rep.int(NA, length(x)))[o]
    }
    join_values = head(foo(unique(df_new$group)), -1L)
    # [1] "a" NA  "b" NA  "c" NA  "d"
    

    然后是setkey()join

    setkey(setDT(df_new), group)
    df_new[.(join_values), allow.cartesian=TRUE]
    #     group xvalue yvalue
    #  1:     a     16      1
    #  2:    NA     NA     NA
    #  3:     b     17      2
    #  4:     b     18      3
    #  5:    NA     NA     NA
    #  6:     c     19      4
    #  7:     c     20      5
    #  8:     c     21      6
    #  9:    NA     NA     NA
    # 10:     d     22      7
    # 11:     d     23      8
    # 12:     d     24      9
    # 13:     d     25     10
    

    【讨论】:

    • 您认为这会以某种方式提高性能吗?因为 akrun 解决方案对我来说似乎很地道
    • @DavidArenburg,我不明白为什么他们中的任何一个都应该是惯用的here。这只是另一种方式。我使用 joins 是因为它直接给出了答案,而不必稍后用 NA 替换。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 1970-01-01
    • 2013-05-15
    • 2017-01-02
    相关资源
    最近更新 更多