【问题标题】:Converting a data frame to a matrix with plyr daply使用 plyr daply 将数据帧转换为矩阵
【发布时间】:2011-08-10 04:56:17
【问题描述】:

我正在尝试使用 plyr 包中的 daply 函数,但无法正确输出。尽管构成矩阵的变量是数字,但矩阵的元素是列表,而不是变量本身。例如,这里是数据的一小部分:

   Month Vehicle Samples
1 Oct-10   31057     256
2 Oct-10   31059     316
3 Oct-10   31060     348
4 Nov-10   31057     267
5 Nov-10   31059     293
6 Nov-10   31060     250
7 Dec-10   31057     159
8 Dec-10   31059     268
9 Dec-10   31060     206

我希望能够以矩阵格式可视化数据,看起来像这样:

  Month
Vehicle Oct-10 Nov-10 Dec-10
  31057    256    267    159
  31059    316    293    268
  31060    348    250    206

这是我使用的几种替代语法(后者是因为我的原始数据框的列比我在此处显示的要多):

daply(DF, .(Vehicle, Month), identity)
daply(DF,.(Vehicle,Month), colwise(identity,.(Samples)))

然而我得到的却是相当深奥:

       Month
Vehicle Oct-10 Nov-10 Dec-10
  31057 List,3 List,3 List,3
  31059 List,3 List,3 List,3
  31060 List,3 List,3 List,3

正如一些评论者所建议的,我在输出中使用了str 函数,下面是摘录:

List of 9
 $ :'data.frame':       1 obs. of  3 variables:
  ..$ Month  : Ord.factor w/ 3 levels "Oct-10"<"Nov-10"<..: 1
  ..$ Vehicle: Factor w/ 3 levels "31057","31059",..: 1
  ..$ Samples: int 256
 $ :'data.frame':       1 obs. of  3 variables:
  ..$ Month  : Ord.factor w/ 3 levels "Oct-10"<"Nov-10"<..: 1
  ..$ Vehicle: Factor w/ 3 levels "31057","31059",..: 2
  ..$ Samples: int 316

我错过了什么?另外,有没有办法简单地使用基本包来做到这一点?谢谢!

下面是数据框的Dput,如果您想重现此内容:

structure(list(Month = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 3L, 
3L, 3L), .Label = c("Oct-10", "Nov-10", "Dec-10"), class = c("ordered", 
"factor")), Vehicle = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 
2L, 3L), .Label = c("31057", "31059", "31060"), class = "factor"), 
    Samples = c(256L, 316L, 348L, 267L, 293L, 250L, 159L, 268L, 
    206L)), .Names = c("Month", "Vehicle", "Samples"), class = "data.frame", row.names = c(NA, 
9L))

【问题讨论】:

  • 更多信息会很有用。尝试 str(DF) 并将输出粘贴到问题中。或者使用 dput(DF) 为人们提供你的数据,如果它不是很大的话(如果它是子集的话)。
  • 您在这里尝试做什么并不明显。您似乎正在尝试对数据进行某种形式的重塑,因为 identity 不会对其参数执行任何操作。请告诉我们您的预期结果。
  • 请参阅stackoverflow.com/questions/5963269/…,了解如何使您的问题中的代码可重现。
  • 感谢您的编辑;这个问题现在好多了!这确实被称为重塑数据;使用该术语(和 R 标签)进行搜索会给出一些对您有帮助的结果:stackoverflow.com/search?q=%5Br%5D+reshape 我还在下面回答了您的问题,具体说明了为什么identity 不起作用。
  • stackoverflow.com/a/9617424/210673 现在列出了执行此操作的各种方法。

标签: r dataframe plyr


【解决方案1】:

identity 函数不是您想要的;来自帮助页面,“所有 plyr 函数都使用相同的拆分-应用-组合策略:它们将输入拆分为更简单的部分,将 .fun 应用于每个部分,然后将这些部分组合成一个数据结构。”在这种情况下,较简单的部分是原始数据帧的子集,具有唯一的车辆/月份组合;恒等函数只返回该子集,然后使用这些子集填充结果矩阵。

也就是说,您获得的矩阵的每个元素都是一个数据框(它是一种列表),其中包含具有该月份/车辆组合的行。

> try1 <- daply(DF, .(Vehicle, Month), identity)
> try1[1,1]
[[1]]
   Month Vehicle Samples
1 Oct-10   31057     256

您希望使用一个函数来获取该数据帧的 Samples 部分,如下所示:

daply(DF, .(Vehicle, Month), function(x) x$Samples)

导致

       Month
Vehicle Oct-10 Nov-10 Dec-10
  31057    256    267    159
  31059    316    293    268
  31060    348    250    206

使用reshape 包中的cast(它返回一个数据框)可以实现这一点

cast(DF, Vehicle~Month, value="Samples")

reshape2中的修改版;第一个返回一个数据框,第二个返回一个矩阵

dcast(DF, Vehicle~Month, value_var="Samples")
acast(DF, Vehicle~Month, value_var="Samples")

xtabs 来自 stats

xtabs(Samples ~ Vehicle + Month, DF)

或者手动,使用矩阵索引一点也不难;几乎所有的代码都只是设置矩阵。

with(DF, {
  out <- matrix(nrow=nlevels(Vehicle), ncol=nlevels(Month),
                dimnames=list(Vehicle=levels(Vehicle), Month=levels(Month)))
  out[cbind(Vehicle, Month)] <- Samples
  out
})

stats 包中的reshape 函数也可以用来做这个,但是语法比较难,自从从reshape 包中学习castmelt 之后就没有用过一次。

【讨论】:

  • 谢谢,比我希望的更有帮助!它还帮助我克服了对 d*ply 函数的误解,即它首先创建了作为数据帧的子集。
【解决方案2】:

如果我们在标题中使用 OP,那么他们可能正在寻找 data.matrix(),这是 R 中始终可用的 base 包中的标准函数。

data.matrix() 在将数据帧转换为矩阵之前将任何因子转换为其数字编码。考虑以下数据框:

dat <- data.frame(A = 1:10, B = factor(sample(c("X","Y"), 10, replace = TRUE)))

如果我们通过as.matrix() 进行转换,我们会得到一个字符矩阵:

> head(as.matrix(dat))
     A    B  
[1,] " 1" "X"
[2,] " 2" "X"
[3,] " 3" "Y"
[4,] " 4" "Y"
[5,] " 5" "Y"
[6,] " 6" "Y"

或者如果通过matrix() 获得一个带有维度的列表(一个列表数组 - 顺便提一下?daplyValue 部分)

> head(matrix(dat))
     [,1]      
[1,] Integer,10
[2,] factor,10 
> str(matrix(dat))
List of 2
 $ : int [1:10] 1 2 3 4 5 6 7 8 9 10
 $ : Factor w/ 2 levels "X","Y": 1 1 2 2 2 2 1 2 2 1
 - attr(*, "dim")= int [1:2] 2 1

data.matrix(),然而,做了预期的事情:

> mat <- data.matrix(dat)
> head(mat)
     A B
[1,] 1 1
[2,] 2 1
[3,] 3 2
[4,] 4 2
[5,] 5 2
[6,] 6 2
> str(mat)
 int [1:10, 1:2] 1 2 3 4 5 6 7 8 9 10 ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:2] "A" "B"

【讨论】:

    猜你喜欢
    • 2021-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    • 2015-10-01
    • 2018-08-05
    • 2016-08-03
    相关资源
    最近更新 更多