【问题标题】:Rearranging a dataframe in R在 R 中重新排列数据框
【发布时间】:2012-10-01 03:03:26
【问题描述】:

我有一个如下所示的数据框:

created_at  actor_attributes_email      type
3/11/12 7:28    jeremy@asynk.ch         PushEvent
3/11/12 7:28    jeremy@asynk.ch         PushEvent
3/11/12 7:28    jeremy@asynk.ch         PushEvent
3/11/12 7:42    jeremy@asynk.ch         IssueCommentEvent
3/11/12 11:06   d.bussink@gmail.com     PushEvent
3/11/12 11:06   d.bussink@gmail.com     PushEvent

现在我想按月/年重新排列它(仍然按时间排序,并且仍然保持行的完整性)。这应该为每个月创建 3 列,然后将与该月相关的所有数据(created_at、actor_attributes_email 和类型)放在这 3 列中,以便我得到以下标题(对于数据中存在的所有月份):

april_2011_created_at april_2011_actor_attributes_email april_2011_type may_2011_created_at may_2011_actor_attributes_email may_2011_type  

如何在 R 中完成此操作?

可在此处找到包含整个数据集的 CSV 文件: https://github.com/aronlindberg/VOSS-Sequencing-Toolkit/blob/master/rubinius_rubinius_sequencing/rubinius_6months.csv

这是 CSV 第一行的dput()

structure(list(created_at = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 
3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L, 6L, 6L, 6L, 7L, 7L, 7L, 8L, 
8L, 8L, 9L, 9L, 9L, 10L, 10L, 10L), .Label = c("2012-03-11 07:28:04", 
"2012-03-11 07:28:19", "2012-03-11 07:42:16", "2012-03-11 11:06:13", 
"2012-03-11 12:46:25", "2012-03-11 13:03:12", "2012-03-11 13:12:34", 
"2012-03-11 13:14:52", "2012-03-11 13:30:14", "2012-03-11 13:30:48"
), class = "factor"), actor_attributes_email = structure(c(3L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c("", 
"d.bussink@gmail.com", "jeremy@asynk.ch"), class = "factor"), 
    type = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L), .Label = c("IssueCommentEvent", "PushEvent"
    ), class = "factor")), .Names = c("created_at", "actor_attributes_email", 
"type"), class = "data.frame", row.names = c(NA, -30L))

其他一些假设是:

  • 即使“PushEvent”(例如)重复 10 次,我也需要保留所有这些,因为我将使用 R 包 TraMineR 进行序列分析
  • 列可以不等长
  • 不同月份的列之间没有关系
  • 某月内的数据按最早的时间排序
  • 例如 2011 年 6 月和 2012 年 6 月的数据需要位于不同的列中

【问题讨论】:

    标签: r data-manipulation traminer


    【解决方案1】:

    Maiasaura 提供了一种使用 plyr 和 lubridate 完成工作的优雅方式。这是在基本 R 中实现它的稍微不那么优雅的方式。但与 Maiasaura 不同的是,这种方式最大限度地减少了 NA 行的数量。每个月的NA 行数是该月的行数与任何月份的最大行数之差。

    # split df by month
    by.mon <- split(df, months(as.POSIXct(df$created_at)))
    
    # rename the columns to include the month name
    by.mon <- mapply(
        function(x, mon.name) {
            names(x) <- paste(mon.name, names(x), sep='_');
            return(x)
        }, x=by.mon, mon.name=names(by.mon), SIMPLIFY=FALSE)
    
    # add an index column for merging on
    by.mon.indexed <- lapply(by.mon, function(x) within(x, index <- 1:nrow(x)))
    
    # merge all of the months together
    results <- Reduce(function(x, y) merge(x, y, by='index', all=TRUE, sort=FALSE), 
        by.mon.indexed)
    
    # remove the index column
    final_result <- results[names(results) != 'index']
    

    【讨论】:

    • 谢谢!有没有办法确保月份按顺序排列?
    • 您可以使用by.mon &lt;- by.mon[order(match(names(by.mon), month.name))]by.mon 进行排序,这样就可以了。
    • 是否可以让今年也对年份敏感?现在它将 2011 年 6 月和 2012 年 6 月的事件放在同一列中。
    【解决方案2】:
    library(plyr)
    library(lubridate)
    df$created_at <- ymd_hms(df$created_at, quiet = TRUE)
    df$mname <- as.character(lubridate::month(df$created_at,label = T, abbr = T))
    result <- dlply(df, .(mname), function(x){
          x <- arrange(x, created_at)
          names(x) <- paste0(unique(x$mname), "_", names(x))
          x$mname <- NULL
          x
        }, .progress = 'text')
    
    final_result <- ldply(result, rbind.fill)[, -1]
    

    请注意,由于您希望将月份名称附加到 3 个列名称并填写适当的数据,因此所有没有数据的列将仅填充 NAs(这是 @ 的预期行为987654323@)。

    【讨论】:

    • 对您和 mplourde 能够理解问题陈述印象深刻。
    • 谢谢。然而,这以一种不方便的方式交错出现,即如果四月在第 1543 行结束,那么五月从第 1544 行开始)。有没有办法确保每个月的​​数据从第 2 行开始(即在标题之后)?另外,如何使月份按时间顺序排列?
    • 将每个月作为一列确实会使它变得非常宽。如果跳过最后一行,result 列表将只有每个月,可以轻松地将其写入 data.frame 或进一步处理,而无需组合成一个巨大的笨拙的 data.frame(我认为您出于某种原因需要它)。
    • 是否可以让今年也对年份敏感?现在它将 2011 年 6 月和 2012 年 6 月的事件放在同一列中。
    猜你喜欢
    • 2013-07-03
    • 1970-01-01
    • 2014-06-23
    • 2015-09-25
    • 1970-01-01
    • 2018-07-18
    • 2013-10-21
    • 1970-01-01
    相关资源
    最近更新 更多