【问题标题】:Combine different rowcells from a data.table or data.frame based on simple condition根据简单条件组合来自 data.table 或 data.frame 的不同行单元
【发布时间】:2014-06-24 19:07:54
【问题描述】:

我有一个看起来像这样的 data.frame

dput(repex) = structure(list(cat = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L), .Label = c("x", 
"y", "z"), class = "factor"), year = c(1980, 1980, 1982, 1982, 
1990, 1991, 1991, 1991, 1993, 1981, 1981, 1983, 1990, 1996, 1996, 
1996, 1996, 1999, 2002, 1994), org = structure(c(2L, 3L, 4L, 
2L, 5L, 6L, 7L, 8L, 9L, 2L, 3L, 5L, 3L, 10L, 11L, 4L, 9L, 10L, 
3L, 9L), .Label = c("709340", "a", "b", "c", "d", "f", "j", "k", 
"e", "h", "m"), class = "factor")), .Names = c("cat", "year", 
"org"), row.names = c(NA, 20L), class = "data.frame")

我想创建一个新对象(最好是 data.table 或 data.frame),其中 org 的元素水平分组在特定的 cat, year 组合后面

我尝试运行以下命令:

repex <- data.table(repex)
setkey(repex,cat,year)
repex[, list(org), by="cat,year"]  #OR
repex[, paste(org,sep="_"), by="cat,year"] # OR
with(repex, tapply(org,paste(cat,year,sep="_"),paste))

前两个 data.table 选项仅复制整个 data.table 和 tapply 选项(应用于 repex 作为 data.table 或 data.frame)适用于小型数据集,但创建一个不太方便的列表对象因为我需要将输出添加到另一个基于 cat_year 组合的 data.frame... 此外,对于一个长数据集(nrow > 100,000),它需要永远,特别是在某些情况下它需要粘贴 > 100 org-变种。

我想要的输出是一个看起来像这样的 data.table

x 1980 a b
x 1982 a c # org would ideally be rearranged
x 1990 d
x 1991 f j k 
...
y 1996 c e h m
...
z 2002 b

【问题讨论】:

    标签: r dataframe aggregate data.table apply


    【解决方案1】:

    @Anandaaaaaaaaaaaaaaaa,

    这是我自己解决问题的不雅方法。我相信有一种更简单的方法可以采纳您的建议,但我也想分享一下。

    第 1 步:将所有 org 粘贴到列表中

    tmp1 <- with(repex, tapply(org,paste(cat,year,sep="_"), paste))
    

    第 2 步:查找列表的最长长度(非常不雅)

    x<-as.vector(NA)
    for (i in 1:length(fy_ids)) {
      x[i] <- length(fy_ids[[i]])
      }
    max(x)
    

    第 3 步:使用 x 的最大值,构造一个 data.frame,其中每个组织都出现在一个新单元格中(特别感谢@agstudy 提供了previous answer

    tmp <- do.call(rbind,lapply(tmp1,
                   function(y)
                     if(length(y)>0)c(y,rep(NA, max(x)-length(y)))
                                 else c(y,rep(NA,max(x)))))
    

    第四步:将tmp转成data.frame

    tmp &lt;- data.frame(tmp)

    我知道这很麻烦,但它的优点是可以更轻松地搜索特定的 org,因为每个 org 都出现在不同的单元格中。

    【讨论】:

    • 我不会对此投反对票,因为它确实试图回答问题 (+1),即使它更多地表现为长评论。但是,这不是一种有效的方法。我在你的另一个更有效的问题上添加了一个替代 agstudy 的答案(即使它可能需要更多的代码设置时间)。哦,还有名字叫 Ananda :-)
    • 感谢@AnandaMahto 的出色回答以及在我更改最初的问题时对我的包容。我也很欣赏你的“不反对”行动:)。
    【解决方案2】:

    您的一个实际问题是对paste 使用了不正确的参数。您正在寻找collapse,而不是sep。另一个问题是错误地使用了“data.table”语法。


    更新

    考虑到这个答案的 cmets,我建议改为:

    library(data.table)
    library(reshape2)
    DT <- as.data.table(repex)
    
    setkey(DT, cat, year, org) ## Sorts everything
    
    ## Creates a column "var" with the sequence of values ("V1", "V2", and so on)
    DT[, var := paste("V", sequence(.N), sep = ""), by = list(cat, year)]
    head(DT)
    #    cat year org var
    # 1:   x 1980   a  V1
    # 2:   x 1980   b  V2
    # 3:   x 1982   a  V1
    # 4:   x 1982   c  V2
    # 5:   x 1990   d  V1
    # 6:   x 1991   f  V1
    

    将其转换为“宽”格式:

    dcast.data.table(DT, cat + year ~ var, value.var="org")
    #     cat year V1 V2 V3 V4
    #  1:   x 1980  a  b NA NA
    #  2:   x 1982  a  c NA NA
    #  3:   x 1990  d NA NA NA
    #  4:   x 1991  f  j  k NA
    #  5:   x 1993  e NA NA NA
    #  6:   y 1981  a  b NA NA
    #  7:   y 1983  d NA NA NA
    #  8:   y 1990  b NA NA NA
    #  9:   y 1996  c  e  h  m
    # 10:   z 1994  e NA NA NA
    # 11:   z 1999  h NA NA NA
    # 12:   z 2002  b NA NA NA
    

    原答案

    这是一个非常简单的aggregate 问题:

    aggregate(org ~ cat + year, repex, function(x) paste(sort(x), collapse = " "))
    #    cat year     org
    # 1    x 1980     a b
    # 2    y 1981     a b
    # 3    x 1982     a c
    # 4    y 1983       d
    # 5    x 1990       d
    # 6    y 1990       b
    # 7    x 1991   f j k
    # 8    x 1993       e
    # 9    z 1994       e
    # 10   y 1996 c e h m
    # 11   z 1999       h
    # 12   z 2002       b
    

    “data.table”方法:

    library(data.table)
    DT <- as.data.table(repex)
    DT[, list(org = paste(sort(org), collapse = " ")), by = list(cat, year)]
    

    而且,为了解决问题,采用“dplyr”方法:

    library(dplyr)
    repex %.% group_by(cat, year) %.% summarise(org = paste(sort(org), collapse = " "))
    

    【讨论】:

    • 您好,感谢您的有用回复。同时,我设法自己设计了一种不太优雅的解决方案。所以我将使用您的聚合或 data.table 之一(dplyr 语法太可怕了:)。但是,有没有办法改变collapse 命令,使不同的org 最终出现在不同的矩阵单元中?所以对于 x 1980 org1 将是 a 而 org2 (另一列)将是 b ...
    • @Arun,我检查了示例数据集,这创建了一个实际上比我想到的解决方案更好的解决方案,因为它在单独的列中订购了 org,这对于以后的搜索目的来说非常棒.不幸的是,在我的数据集中有 > 14,500 个不同的组织和 > 40,000 个不同的 cat(类别的缩写),它会产生数据处理问题,因为结果对象 > 2 GB。有解决办法吗?
    • @Arun 我猜你是对的。在我自己提出的解决方案中,我避免了这种情况。在我的数据集中,必要的最大宽度是 464(即在特定年份有 464 个组织在同一类别中处于活动状态)。与dcast 格式相比,我可以将这些 464 整齐地绘制到不同的单元格中,并创建更少的 NA。尽管如此,每个组织的私人专栏都会对网络分析进行特定计数和形式(例如,特定org 在特定cat 在“t”年的活动如何影响其他org 在类似cat 在“年” t+1") 更易于可视化!感谢您的解决方案!!!
    • 感谢您的出色建议。 @Arun 唯一值的总数超过 33,000 个,但每行不超过 464 个。@ AnandaMahto 的解决方案基本上将您的建议与内存密集度较低的方法相结合。太完美了!
    • 我只是在我的整个数据集上运行它,它的运行速度比我提出的解决方案快得多。唯一的缺点是dcast 中的列顺序不方便,因为它是 V1 V100 V101...
    猜你喜欢
    • 1970-01-01
    • 2021-11-27
    • 1970-01-01
    • 2018-03-13
    • 1970-01-01
    • 2018-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多