重塑 table 以创建按前缀聚合的时间序列

Reshape table to create time series aggregated by prefix

我有一个 table 类似于以下内容:

name,time_in,time_out
jim,1/1/2000 08:24,1/1/2000 15:24
jim,1/2/2000 08:13,1/2/2000 16:24
jim,1/3/2000 08:14,1/3/2000 15:25
jim,1/4/2000 08:33,1/4/2000 16:23
linda,1/1/2000 08:24,1/1/2000 15:24
mark,1/2/2000 08:13,1/2/2000 16:24
mark,1/3/2000 08:14,1/3/2000 15:25
mark,1/4/2000 08:33,1/4/2000 16:23

忽略实际时间,重点是天数不一致。我在 re-shaping 中看到的大部分内容都很好而且方正,我的数据最终可能会被稀疏重塑。有没有一种简单的方法(寻找 R 解决方案,但对 Excel 或任何快速开放)来创建类似于以下内容的 table 聚合:

jim,1/1/2000 08:24,1/1/2000 15:24,1/2/2000 08:13,1/2/2000 16:24,1/3/2000 08:14,1/3/2000 15:25,1/4/2000 08:33,1/4/2000 16:23
linda,1/1/2000 08:24,1/1/2000 15:24
mark,1/2/2000 08:13,1/2/2000 16:24,1/3/2000 08:14,1/3/2000 15:25,1/4/2000 08:33,1/4/2000 16:23

其中每个人聚合到一行(此时也不知道如何处理headers,欢迎提出建议。)

假设所有要聚合的同名行都是连续的,这个Python脚本

from itertools import groupby

with open('infile.txt') as in_f, open('outfile.txt', 'w') as out_f:
    next(in_f)  # skip header
    aggr = groupby(in_f, lambda line: line.partition(',')[0])
    for k, lines in aggr:
        slines = (l.lstrip(k+',').rstrip() for l in lines)
        out_line = k+','+','.join(slines)+'\n'
        out_f.write(out_line)

成功了。

例如,输入文件为

name,time_in,time_out
jim,1/1/2000 08:24,1/1/2000 15:24
jim,1/2/2000 08:13,1/2/2000 16:24
jim,1/3/2000 08:14,1/3/2000 15:25
jim,1/4/2000 08:33,1/4/2000 16:23
linda,1/1/2000 08:24,1/1/2000 15:24
mark,1/2/2000 08:13,1/2/2000 16:24
mark,1/3/2000 08:14,1/3/2000 15:25
mark,1/4/2000 08:33,1/4/2000 16:23

它产生一个

的输出文件
jim,1/1/2000 08:24,1/1/2000 15:24,1/2/2000 08:13,1/2/2000 16:24,1/3/2000 08:14,1/3/2000 15:25,1/4/2000 08:33,1/4/2000 16:23
linda,1/1/2000 08:24,1/1/2000 15:24
mark,1/2/2000 08:13,1/2/2000 16:24,1/3/2000 08:14,1/3/2000 15:25,1/4/2000 08:33,1/4/2000 16:23

它利用了itertools.groupby

的力量

基本上,只要前缀(即名称)不变,它就会对行进行分组。当它这样做时,它继续前进,在新发现的前缀上创建另一个组。 然后它简单地将每个组的元素连接在一行上,用 ','

分隔

注意:如果您希望 header 出现在输出文件中,请更改行

    next(in_f)  # skip header

    out_f.write(next(in_f))  # write and skip header

考虑这个基本的 R 解决方案,它对不同的名称使用 运行 计数,并按计数从长到宽进行整形:

# RECREATING DATA FRAME
df <- data.frame(name = c("Jim", "Jim", "Jim", "Jim", "linda", "mark", "mark", "mark"),
       time_in = c("1/1/2000 8:24", "1/2/2000 08:13", "1/3/2000 08:14", "1/4/2000 08:33",
                   "1/1/2000 08:24", "1/2/2000 08:13", "1/3/2000 08:14", "1/4/2000 08:33"),
       time_out = c("1/1/2000 15:24", "1/2/2000 16:24", "1/3/2000 15:25", "1/4/2000 16:23",
                    "1/1/2000 15:24", "1/2/2000 16:24", "1/4/2000 15:25", "1/4/2000 16:23"))

# COUNTING BY GROUPED NAMES
df$numcount <- sapply(1:nrow(df),
                      function(i) sum(df[1:i, c("name")] == df$name[i]))

# RESHAPING LONG TO WIDE
reshapedf <- reshape(df, v.names = c("time_in", "time_out"), 
                           timevar=c("numcount"), idvar = c("name"), 
                           direction = "wide")

row.names(reshapedf) <- NULL

reshapedf

输出

   name      time_in.1     time_out.1      time_in.2     time_out.2      time_in.3     time_out.3      time_in.4     time_out.4
1   Jim  1/1/2000 8:24 1/1/2000 15:24 1/2/2000 08:13 1/2/2000 16:24 1/3/2000 08:14 1/3/2000 15:25 1/4/2000 08:33 1/4/2000 16:23
2 linda 1/1/2000 08:24 1/1/2000 15:24           <NA>           <NA>           <NA>           <NA>           <NA>           <NA>
3  mark 1/2/2000 08:13 1/2/2000 16:24 1/3/2000 08:14 1/4/2000 15:25 1/4/2000 08:33 1/4/2000 16:23           <NA>           <NA>