【问题标题】:Simple function does not work for `dcast` - reshape2简单功能不适用于`dcast` - reshape2
【发布时间】:2015-08-04 08:35:43
【问题描述】:

假设我有这个数据:

 c1 c2 c3
 A  A  AA
 A  B  BB
 A  C  CC
 B  A  DD
 B  B  EE
 B  C  FF
 C  A  GG
 C  B  HH
 C  C  II
 A  A  JJ

我想用 dcast 用这个函数重塑它们:

dcast(data,c1~c2,value.var="c3",function(x)x)

但我收到此错误:

Error in vapply(indices, fun, .default) : values must be length 0,
 but FUN(X[[1]]) result is length 1

如何通过dcast(用户定义函数)使用新函数。

我想得到:

  A   B   C
A AA BB  CC
B DD EE  FF
C GG HH  II
A JJ NA  NA

【问题讨论】:

  • 什么function(x)x?你想要的输出是什么?
  • 一个虚拟函数返回value.var而不做改变。
  • 所以请让您的示例可重现并提供您想要的确切输出。
  • 最后一行不是应该有JJ吗?
  • @Henrik 好的,我删除了答案。快乐:-)

标签: r reshape


【解决方案1】:

这是使用data.tables v 1.9.5+ 新的rleid 函数的可能解决方案,它将为c1 列创建索引(如果需要,您可以在之后删除indx

library(data.table) # v 1.9.5+
dcast(setDT(stocksm)[, indx := rleid(c1)], indx + c1 ~ c2, value.var = "c3")
#    indx c1  A  B  C
# 1:    1  A AA BB CC
# 2:    2  B DD EE FF
# 3:    3  C GG HH II
# 4:    4  A JJ NA NA

### installing the development version
# library(devtools)
# install_github("Rdatatable/data.table", build_vignettes = FALSE)

所以基本上在c1 上创建索引后,我们或多或少地像以前一样传播数据,同时将indx 包含在里面


或者如果你坚持tidyr,这里有一个选项

library(tidyr)
stocksm$indx <- with(rle(as.character(stocksm$c1)), rep(seq_along(lengths), lengths))
spread(stocksm, c2, c3)
#   c1 indx  A    B    C
# 1  A    1 AA   BB   CC
# 2  A    4 JJ <NA> <NA>
# 3  B    2 DD   EE   FF
# 4  C    3 GG   HH   II

【讨论】:

  • tidyr 包有spread 功能,能不能产生同样的结果。
【解决方案2】:

使用dcast 的另一种方法是使用cumsum 创建唯一标识符。如果没有创建,该函数将不知道要为 A A 之类的重复项填写哪个值。

data$ids <- cumsum(c(T,diff(as.numeric(data$c1)) != 0L))
dcast(data, ids+c1~c2, value.var="c3")[-1]
#   c1  A    B    C
# 1  A AA   BB   CC
# 2  B DD   EE   FF
# 3  C GG   HH   II
# 4  A JJ <NA> <NA>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-27
    • 2012-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多