首页 文章

使用R透视CSV文件

提问于
浏览
2

我有一个看起来像这样的文件:

type          created_at repository_name
1         IssuesEvent 2012-03-11 06:48:31       bootstrap
2         IssuesEvent 2012-03-11 06:48:31       bootstrap
3         IssuesEvent 2012-03-11 06:48:31       bootstrap
4         IssuesEvent 2012-03-11 06:52:50       bootstrap
5         IssuesEvent 2012-03-11 06:52:50       bootstrap
6         IssuesEvent 2012-03-11 06:52:50       bootstrap
7   IssueCommentEvent 2012-03-11 07:03:57       bootstrap
8   IssueCommentEvent 2012-03-11 07:03:57       bootstrap
9   IssueCommentEvent 2012-03-11 07:03:57       bootstrap
10        IssuesEvent 2012-03-11 07:03:58       bootstrap
11        IssuesEvent 2012-03-11 07:03:58       bootstrap
12        IssuesEvent 2012-03-11 07:03:58       bootstrap
13         WatchEvent 2012-03-11 07:15:44       bootstrap
14         WatchEvent 2012-03-11 07:15:44       bootstrap
15         WatchEvent 2012-03-11 07:15:44       bootstrap
16         WatchEvent 2012-03-11 07:18:45        hogan.js
17         WatchEvent 2012-03-11 07:18:45        hogan.js
18         WatchEvent 2012-03-11 07:18:45        hogan.js

我正在使用的数据集可以在https://github.com/aronlindberg/VOSS-Sequencing-Toolkit/blob/master/twitter_exploratory_analysis/twitter_events_mini.csv上访问 .

我想创建一个表,其中包含“repository_name”列中每个条目的列(例如bootstrap,hogan.js) . 在该列中,我需要从“类型”列中获取与该条目对应的数据(即,只有当前“类型”列的行,当前“repository_name”列中的值“bootstrap”应该属于新的“bootstrap”专栏) . 因此:

  • 时间戳仅用于排序,不需要跨行同步(实际上它们可以删除,因为数据已根据时间戳排序)

  • 即使"IssuesEvent"重复10次,我也需要保留所有这些,因为我将使用R包TraMineR进行序列分析

  • 列的长度可以不等

  • 不同仓库的列之间没有关系("repository_name")

换句话说,我想要一个看起来像这样的表:

bootstrap            hogan.js
1    IssuesEvent          PushEvent
2    IssuesEvent          IssuesEvent
3    OssueCommentEvent    WatchEvent

我怎样才能在R中实现这一目标?

我可以在https://github.com/aronlindberg/VOSS-Sequencing-Toolkit/blob/master/twitter_exploratory_analysis/reshaping_bigqueries.R找到一些使用重塑包的失败尝试 .

3 回答

  • 5

    您的样本数据:

    data <- structure(list(type = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 1L, 
    1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("IssueCommentEvent", 
    "IssuesEvent", "WatchEvent"), class = "factor"), created_at = structure(c(1L, 
    1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L, 6L, 6L, 
    6L), .Label = c("2012-03-11 06:48:31", "2012-03-11 06:52:50", 
    "2012-03-11 07:03:57", "2012-03-11 07:03:58", "2012-03-11 07:15:44", 
    "2012-03-11 07:18:45"), class = "factor"), repository_name = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
    2L), .Label = c("bootstrap", "hogan.js"), class = "factor")), .Names = c("type", 
    "created_at", "repository_name"), class = "data.frame", row.names = c(NA, 
    -18L))
    

    我从您的预期输出中收集到,当它显示多次相同的 created_at 值时,您只需要一个 type ,换句话说,您想要删除重复项:

    data <- unique(data)
    

    然后,按照它们出现的顺序每 repository_name 提取所有 type 条目,您只需使用:

    data.split <- split(data$type, data$repository_name)
    data.split
    # $bootstrap
    # [1] IssuesEvent       IssuesEvent       IssueCommentEvent
    # [4] IssuesEvent       WatchEvent       
    # Levels: IssueCommentEvent IssuesEvent WatchEvent
    # 
    # $hogan.js
    # [1] WatchEvent
    # Levels: IssueCommentEvent IssuesEvent WatchEvent
    

    它返回一个列表,该列表是具有不同长度的向量集合的首选R数据结构 .

    Edit: 既然您已经提供了输出数据的示例,那么您的预期输出确实是data.frame就会变得更加明显 . 您可以使用以下函数将上面的列表转换为使用 NA 填充的data.frame:

    list.to.df <- function(arg.list) {
       max.len  <- max(sapply(arg.list, length))
       arg.list <- lapply(arg.list, `length<-`, max.len)
       as.data.frame(arg.list)
    }
    
    df.out <- list.to.df(data.split)
    df.out
    #           bootstrap   hogan.js
    # 1       IssuesEvent WatchEvent
    # 2       IssuesEvent       <NA>
    # 3 IssueCommentEvent       <NA>
    # 4       IssuesEvent       <NA>
    # 5        WatchEvent       <NA>
    

    然后,您可以使用该文件将其保存到文件中

    write.csv(df.out, file = "out.csv", quote = FALSE, na = "", row.names = FALSE)
    

    获得与您在github上发布的格式完全相同的输出格式 .

  • 1

    我刚加入stackoverflow;希望我的回答有点用处 .

    通过表格,我假设你的意思是你想要一个数据框架 . 但是,列似乎不太可能具有相同的长度,并且看起来行无论如何都没有多大意义 . 也许列表会更好?

    这是一个混乱的解决方案:

    names <- unique(olddataframe$repository_name)
    results <- sapply(1:length(names), function(j){
        sapply(which(olddataframe$repository_name == names[j]), function(i){
            olddataframe$type[i]
       )
    })
    names(results) <- names
    results
    
  • 5

    使用@ flodel的 data 对象,您也可以尝试 aggregate() ,但是对于许多事件类型,这很快就会变得不可读:

    aggregate(list(Type = unique(data)$type), 
              list(Repository = unique(data)$repository_name), 
              function(x) paste0(x))
    #   Repository                                                                 Type
    # 1  bootstrap IssuesEvent, IssuesEvent, IssueCommentEvent, IssuesEvent, WatchEvent
    # 2   hogan.js                                                           WatchEvent
    

    你也可以试试 reshape() 并用 t() (转置)做一些诡计,如下所示 .

    temp = unique(data)
    temp = reshape(temp, direction = "wide", 
                   idvar="repository_name", timevar="created_at")
    # If you want to keep the times, remove `row.names=NULL` below
    temp1 = data.frame(t(temp[-1]), row.names=NULL)
    names(temp1) = t(temp[1])
    temp1
    #           bootstrap   hogan.js
    # 1       IssuesEvent       <NA>
    # 2       IssuesEvent       <NA>
    # 3 IssueCommentEvent       <NA>
    # 4       IssuesEvent       <NA>
    # 5        WatchEvent       <NA>
    # 6              <NA> WatchEvent
    

    但是,我发现所有这些NAs都是令人讨厌的;我会说,@ flodel的答案是最直接的,也可能是最有用的(从长远来看,也就是说,一旦你获得这种形式的数据,就不知道你想要做什么) .

    更新(更多技巧)

    (实际上,这是“SO非常适合拖延”的时刻)

    我的最终(非常低效)答案如下 .

    按上述步骤操作,但删除日期/时间内容,并将因子转换为字符 .

    # Using @flodel's data
    temp1 = unique(data)[-2]
    # Remove the factors
    temp1[sapply(temp1, is.factor)] = lapply(temp1[sapply(temp1, is.factor)], 
                                             as.character)
    # Split and unlist your data
    temp2 = split(temp1[-c(2:3)], temp1$repository_name)
    temp3 = sapply(temp2, as.vector)
    

    rbind()cbind() 将"recycle"不同长度的对象使它们具有相同的长度,但我们不会在其中提取 temp3 对象中的清理版本的名称 .

    # What is the max number of rows we need?
    LEN = max(sapply(temp3, length))
    # What are the names we want for our columns?
    NAMES = gsub(".type", "", names(temp3))
    

    现在,将 temp3 中的项目提取到工作区中,并确保它们的长度相同 .

    # Use assign to unlist the vectors to the workspace
    for (i in 1:length(temp3)) assign(NAMES[i], temp3[[i]])
    # Make sure they have the same lengths
    length(hogan.js) = LEN
    length(bootstrap) = LEN
    

    最后,使用 cbind() 将数据放在一起 .

    # Use cbind to put these together
    data.frame(cbind(bootstrap, hogan.js))
    #           bootstrap   hogan.js
    # 1       IssuesEvent WatchEvent
    # 2       IssuesEvent       <NA>
    # 3 IssueCommentEvent       <NA>
    # 4       IssuesEvent       <NA>
    # 5        WatchEvent       <NA>
    

相关问题