逐行重塑数据

时间:2014-04-08 17:51:40

标签: r reshape2

我有一个类似于以下示例的数据框:

> df <- data.frame(imp = c("Johny", "Johny", "Lisa", "Max"), item = c(5025, 1101, 2057, 1619))
> df
     imp     item  
[1,] "Johny" "5025"
[2,] "Johny" "1101"
[3,] "Lisa"  "2057"
[4,] "Max"   "1619"

我希望每个user都有一个唯一的行。最终结果应该是这样的:

> df
     imp     item1  item2 
[1,] "Johny" "5025" "1101"
[2,] "Lisa"  "2057" NA    
[3,] "Max"   "1619" NA

4 个答案:

答案 0 :(得分:3)

## Add an ID column to distinguish multiple measurements per imp
## There's probably a better way to do this?
df <- do.call(rbind, lapply(
    split(df, df$imp),
    function(x) {
        x$item_id <- seq(nrow(x))
        return(x)
    }
))

## Then simply use the dcast function from the reshape2 package
df <- dcast(df, imp ~ item_id, value.var='item')

## Tidy up the column names
names(df) <- sub('^(\\d+)$', 'item_\\1', names(df))

答案 1 :(得分:3)

使用data.table v 1.9.6+我们可以将表达式直接传递给公式。有关详情,请参阅?dcast以及示例部分。

require(data.table) # v1.9.6+
dcast(setDT(df), imp ~ paste0("item", 
       df[, seq_len(.N), by=imp]$V1), value.var="item")

#      imp item1 item2
# 1: Johny  5025  1101
# 2:  Lisa  2057    NA
# 3:   Max  1619    NA

修改

使用data.table v1.9.8 +你可以简单地做

require(data.table) # v1.9.8+
dcast(setDT(df), imp ~ rowid(imp, prefix = "item"), value.var = "item")

答案 2 :(得分:1)

使用data.table的方法怎么样:

require(data.table)
dt <- data.table(imp = c("Johny", "Johny", "Lisa", "Max"),
                 item = c(5025, 1101, 2057, 1619))

dt[, list(items = list(unique(item))), by=imp]

# to keep all items, not only uniques
dt[, list(items = list(item)), by=imp]

这为您提供了一个&#34;项目列表&#34;每个&#34; imp&#34; ...

答案 3 :(得分:1)

通过ave(以创建您的&#34;时间&#34;变量)和reshape(来自&#34; long& #34;到&#34;宽&#34;):

df$times <- ave(rep(1, nrow(df)), df$imp, FUN = seq_along)
df
#     imp item times
# 1 Johny 5025     1
# 2 Johny 1101     2
# 3  Lisa 2057     1
# 4   Max 1619     1
reshape(df, direction = "wide", idvar="imp", timevar="times")
#     imp item.1 item.2
# 1 Johny   5025   1101
# 3  Lisa   2057     NA
# 4   Max   1619     NA