我正在尝试学习如何使用R“reshape2”包中的一些函数,特别是dcast
。我正在尝试创建一个表,显示两个软件版本的总和(所有文件的一类数据的总和除以一个“案例”中的最大“RepNum”)和两者之间的百分比变化。 / p>
这是我的数据集的样子(示例数据):
| FileName | Version | Category | Value | TestNum | RepNum | Case |
|:--------:|:-------:|:---------:|:-----:|:-------:|:------:|:-----:|
| File1 | 1.0.18 | Category1 | 32.5 | 11 | 1 | Case1 |
| File1 | 1.0.18 | Category1 | 31.5 | 11 | 2 | Case1 |
| File1 | 1.0.18 | Category2 | 32.3 | 11 | 1 | Case1 |
| File1 | 1.0.18 | Category2 | 31.4 | 11 | 2 | Case1 |
| File2 | 1.0.18 | Category1 | 34.6 | 11 | 1 | Case1 |
| File2 | 1.0.18 | Category1 | 34.7 | 11 | 2 | Case1 |
| File2 | 1.0.18 | Category2 | 34.5 | 11 | 1 | Case1 |
| File2 | 1.0.18 | Category2 | 34.6 | 11 | 2 | Case1 |
| File1 | 1.0.21 | Category1 | 31.7 | 12 | 1 | Case1 |
| File1 | 1.0.21 | Category1 | 32.0 | 12 | 2 | Case1 |
| File1 | 1.0.21 | Category2 | 31.5 | 12 | 1 | Case1 |
| File1 | 1.0.21 | Category2 | 32.4 | 12 | 2 | Case1 |
| File2 | 1.0.21 | Category1 | 31.5 | 12 | 1 | Case1 |
| File2 | 1.0.21 | Category1 | 34.6 | 12 | 2 | Case1 |
| File2 | 1.0.21 | Category2 | 31.7 | 12 | 1 | Case1 |
| File2 | 1.0.21 | Category2 | 32.4 | 12 | 2 | Case1 |
| File1 | 1.0.18 | Category1 | 32.0 | 11 | 1 | Case2 |
| File1 | 1.0.18 | Category1 | 34.6 | 11 | 2 | Case2 |
| File1 | 1.0.18 | Category2 | 34.6 | 11 | 1 | Case2 |
| File1 | 1.0.18 | Category2 | 34.7 | 11 | 2 | Case2 |
| File2 | 1.0.18 | Category1 | 32.3 | 11 | 1 | Case2 |
| File2 | 1.0.18 | Category1 | 34.7 | 11 | 2 | Case2 |
| File2 | 1.0.18 | Category2 | 31.4 | 11 | 1 | Case2 |
| File2 | 1.0.18 | Category2 | 32.3 | 11 | 2 | Case2 |
| File1 | 1.0.21 | Category1 | 32.4 | 12 | 1 | Case2 |
| File1 | 1.0.21 | Category1 | 34.7 | 12 | 2 | Case2 |
| File1 | 1.0.21 | Category2 | 31.5 | 12 | 1 | Case2 |
| File1 | 1.0.21 | Category2 | 34.6 | 12 | 2 | Case2 |
| File2 | 1.0.21 | Category1 | 31.7 | 12 | 1 | Case2 |
| File2 | 1.0.21 | Category1 | 31.4 | 12 | 2 | Case2 |
| File2 | 1.0.21 | Category2 | 34.5 | 12 | 1 | Case2 |
| File2 | 1.0.21 | Category2 | 31.5 | 12 | 2 | Case2 |
实际数据集包含 6 唯一文件,两个最先前的“TestNums& Versions”, 2 唯一类别,以及 4 独特的案例。
利用互联网的魔力,我能够将一个看起来像这样的表拼凑在一起以满足不同的需求(但代码应该类似):
| FileName | Category | 1.0.1 | 1.0.2 | PercentChange |
|:--------:|:---------:|:-----:|:-----:|:-------------:|
| File1 | Category1 | 18.19 | 18.18 | -0.0045808520 |
| File1 | Category2 | 18.05 | 18.06 | -0.0005075721 |
| File2 | Category1 | 19.27 | 18.83 | -0.0224913494 |
| File2 | Category2 | 19.13 | 18.69 | -0.0231780146 |
| File3 | Category1 | 26.02 | 26.91 | 0.0342729019 |
| File3 | Category2 | 25.88 | 26.75 | 0.0335598775 |
| File4 | Category1 | 31.28 | 28.70 | -0.0823371327 |
| File4 | Category2 | 31.13 | 28.56 | -0.0826670833 |
| File5 | Category1 | 31.77 | 25.45 | -01999731215 |
| File5 | Category2 | 31.62 | 25.30 | -0.0117180458 |
| File6 | Category1 | 46.23 | 45.68 | -0.0119578545 |
| File6 | Category2 | 46.08 | 45.53 | -0.0045808520 |
这是制作该表的代码:
vLatest和vPrevious是具有最新和第二个最新版本号的变量
deviations<-subset(df, df$Version %in% c(vLatest, vPrevious))
deviationsCast<-dcast(df[,1:4], FileName + Category ~ Version, value.var = "Value", fun.aggregate=mean)
deviationsCast$PercentChange<-(deviationsCast[,dim(deviationsCast)[2]]-deviationsCast[,dim(deviationsCast)[2]-1])/deviationsCast[,dim(deviationsCast)[2]-1]
我真的只是希望有人能帮助我理解dcast的语法。最初生成的偏差是我对一切如何协同工作最模糊的地方。而不是为文件获取这个,我真的想得到它,以便它为每个类别的所有文件的总和为一个独特的“案例”,并显示它们之间的百分比变化。
| Case | Measure | 1.0.18 | 1.0.21 | PercentChange |
|:------:|:----------:|:------:|:------:|:-------------:|
| Case 1 | Category 1 | 110 | 100 | 9.09% |
| Case 2 | Category 1 | 95 | 89 | 9.32% |
| Case 3 | Category 1 | 92 | 84 | 8.70% |
| Case 4 | Category 1 | 83 | 75 | 9.64% |
| Case 1 | Category 2 | 112 | 101 | 9.82% |
| Case 2 | Category 2 | 96 | 89 | 7.29% |
| Case 3 | Category 2 | 94 | 86 | 8.51% |
| Case 4 | Category 2 | 83 | 76 | 8.43% |
注意:舍入和百分号是加号,但非常优选的加号
这些数字并不反映正确完成的实际数学,只是我在其中放置的随机数字来示例。我希望能够解释我正在努力做的数学计算。
要使用
进行测试的示例数据集FileName<-rep(c("File1","File2","File3","File4","File5","File6"),times=8,each=6)
Version<-rep(c("1.0.18","1.0.21"),times=4,each=36)
Category<-rep(c("Category1","Category2"),times=48,each=3)
Value<-rpois(n=288,lambda=32)
TestNum<-rep(11:12,times=4,each=36)
RepNum<-rep(1:3,times=96)
Case<-rep(c("Case1","Case2","Case3","Case4"),each=72)
df<-data.frame(FileName,Version,Category,Value,TestNum,RepNum,Case)
值得注意的是, df 基本上是 deviations
数据框来自上面的代码(使用vLatest和vPrevious)
MrFlick的答案几乎是完美的但是当我尝试在我的实际数据集中实现它时,我遇到了问题。问题是由于使用vLatest
和vPrevious
作为我的版本而不是仅仅编写字符串。这是我用来获取这两个变量的代码
vLatest<-unique(df[df[,"TestNum"] == max(df$TestNum), "Version"])
vPrevious<-unique(df[df[,"TestNum"] == sort(unique(df$TestNum), T)[2], "Version"])
当我尝试这个时:
pc <- function(a,b) (b-a)/a
summary <- df %>%
group_by(Case, Category, Version) %>%
summarize(Value=mean(Value)) %>%
spread(Version, Value) %>%
mutate(Change=scales::percent(pc(vPrevious,vLatest)))
我收到此错误:Error: non-numeric argument to binary operator
我尝试创建两个TestNum值的新变量(因为它们可能是数值而不需要有因子)。
maxTestNum<-max(df$TestNum)
prevTestNum<-sort(unique(df$TestNum), T)[2]
(我不使用“prevTestNum<-maxTestNum-1
”的原因是因为有时会从数据结果中省略版本)
但是,当我将这两个变量放入代码时,“更改”列的值都是相同的。
答案 0 :(得分:0)
使用OP提供的样本数据集,以及分析编辑,我相信即使使用OP的生产数据集,以下代码也可能产生预期的结果。
我的理解是OP有一个包含许多测试结果的data.frame,但他只希望显示两个最新版本的相对变化。
OP在使用dcast()
功能时请求帮助。此功能可从两个包reshape2
和data.table
获得。这里data.table
版本用于速度和简洁代码。此外,还使用forcats
和formattable
包中的函数。
library(data.table) # CRAN version 1.10.4 used
# coerce to data.table object
DT <- data.table(df)
# reorder factor levels of Version according to TestNum
DT[, Version := forcats::fct_reorder(Version, TestNum)]
# determine the two most recent Versions
# trick: pick 1st and 2nd entry of the _reversed_ levels
vLatest <- DT[, rev(levels(Version))[1L]]
vPrevious <- DT[, rev(levels(Version))[2L]]
# filter DT, reshape from long to wide format,
# compute change for the selected columns using get(),
# use formattable package for pretty printing
summary <- dcast(
DT[Version %in% c(vLatest, vPrevious)],
Case + Category ~ Version, mean, value.var = "Value")[
, PercentChange := formattable::percent(get(vLatest) / get(vPrevious) - 1.0)]
summary
Case Category 1.0.18 1.0.21 PercentChange 1: Case1 Category1 33.00000 31.94444 -3.20% 2: Case1 Category2 31.83333 31.83333 0.00% 3: Case2 Category1 33.05556 33.61111 1.68% 4: Case2 Category2 30.77778 32.94444 7.04% 5: Case3 Category1 33.16667 31.94444 -3.69% 6: Case3 Category2 33.44444 33.72222 0.83% 7: Case4 Category1 30.83333 34.66667 12.43% 8: Case4 Category2 32.27778 33.44444 3.61%
Version
OP已经认识到,按字母顺序排序Version
并不能确保正确的顺序。
sort(paste0("0.0.", 0:12))
[1] "0.0.0" "0.0.1" "0.0.10" "0.0.11" "0.0.12" "0.0.2" "0.0.3" "0.0.4" "0.0.5" [10] "0.0.6" "0.0.7" "0.0.8" "0.0.9"
其中0.0.10
位于0.0.2
之前。
这是至关重要的,因为data.frame()
默认情况下将字符变量转换为因子。
幸运的是,TestNum
与Version
相关联。因此,TestNum
用于借助Version
包中的fct_reorder()
函数重新排序forcats
的因子级别。
这也确保dcast()
以适当的顺序创建新列。
在表达式中使用vLatest / vPrevious
将返回错误消息
vLatest / vPrevious中的错误:二元运算符的非数字参数
这是可以预料到的,因为vLatests
和vPrevious
包含字符值"1.0.21"
和"1.0.18"
,而不能分割。这里的含义是获取vLatests
和vPrevious
给出的列的值并除以。这是通过使用get()
。
当scales::percent()
返回一个字符向量时,formattable::percent()
会返回一个百分比表示的数字向量,即我们仍然可以进行数值计算。
由OP给出:
FileName <- rep(c("File1", "File2", "File3", "File4", "File5", "File6"),
times = 8, each = 6)
Version <- rep(c("1.0.18", "1.0.21"), times = 4, each = 36)
Category <- rep(c("Category1", "Category2"), times = 48, each = 3)
Value <- rpois(n = 288, lambda = 32)
TestNum <- rep(11:12, times = 4, each = 36)
RepNum <- rep(1:3, times = 96)
Case <- rep(c("Case1", "Case2", "Case3", "Case4"), each = 72)
df <- data.frame(FileName, Version, Category, Value, TestNum, RepNum, Case)