我正在尝试使用daply
包中的plyr
函数,但我无法正确输出。即使构成矩阵的变量是数字,矩阵的元素也是列表,而不是变量本身。以下是数据的一小部分,例如:
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))
答案 0 :(得分:7)
identity
功能不是你想要的;在帮助页面中,“所有plyr函数使用相同的split-apply-combine策略:它们将输入分成更简单的部分,将.fun应用于每个部分,然后将这些部分组合成单个数据结构。”在这种情况下,较简单的部分是原始数据框的子集,具有唯一的Vehicle / Month组合; identity函数只返回该子集,然后使用这些子集填充结果矩阵。
也就是说,你得到的矩阵的每个元素都是一个数据框(这是一种列表),其中的行具有月/车组合。
> 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
执行此操作的一些替代方法是使用cast
包中的reshape
(返回数据框)
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
函数也可用于执行此操作,但语法很难,并且自从学习cast
和melt
后我没有使用过它reshape
包。
答案 1 :(得分:2)
如果我们在标题中使用OP,那么他们可能正在寻找data.matrix()
这是 base 包中的标准函数,该函数始终可用于R上。
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()
,则会获得一个包含维度的列表(列表数组 - 正如?daply
中 Value 部分所述)
> 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"