我有一个数据集与4个不同的处理列出在一栏。它们是治疗1、治疗2、治疗3和治疗4,其结果显示在另一列中。我正在尝试转换数据,以便我可以运行一个anova,看看哪种治疗是最有效的。但是当我尝试使用cast函数时,我会得到一条错误消息。我如何将治疗分为4个单独的列,它们在旁边的列中有多有效。还有另一列,列出了观察编号。
发布于 2015-05-12 03:20:19
您可以使用reshape()函数在基R中这样做。演示:
set.seed(1);
df <- data.frame(obs=rep(1:3,each=4), treatment=rep(1:4,3), effect=rnorm(12,50,20) );
df;
## obs treatment effect
## 1 1 1 37.47092
## 2 1 2 53.67287
## 3 1 3 33.28743
## 4 1 4 81.90562
## 5 2 1 56.59016
## 6 2 2 33.59063
## 7 2 3 59.74858
## 8 2 4 64.76649
## 9 3 1 61.51563
## 10 3 2 43.89223
## 11 3 3 80.23562
## 12 3 4 57.79686
reshape(df,dir='w',idvar='obs',timevar='treatment');
## obs effect.1 effect.2 effect.3 effect.4
## 1 1 37.47092 53.67287 33.28743 81.90562
## 5 2 56.59016 33.59063 59.74858 64.76649
## 9 3 61.51563 43.89223 80.23562 57.79686您遇到的问题是您的OBS列在每长格式记录中都是唯一的。reshape()依赖于能够使用idvar来识别何时应该将不同的长格式记录组合成单一的宽格式记录。正如您在上面的示例数据中所看到的,四个带有obs=1的长格式记录被组合成一个单一的宽格式记录,obs=2和obs=3也是如此。
换句话说,在reshape()试图决定如何将data.frame转换为wide格式时,在long格式中唯一的id列是无用的。事实上,除非您创建具有这些键值的并行宽列,否则根本无法保留宽格式的OBS数据,但我认为您不想这样做。
通过将OBS列重新计算为每个宽格式的唯一记录,可以解决这个问题。这可以使用transform()和ave()进行,并通过treatment进行分组,这样每个唯一的treatment都可以获得自己的观察序列。演示:
set.seed(2);
df <- data.frame(obs=1:12, treatment=rep(1:4,3), effect=rnorm(12,50,20) );
df;
## obs treatment effect
## 1 1 1 32.06171
## 2 2 2 53.69698
## 3 3 3 81.75691
## 4 4 4 27.39249
## 5 5 1 48.39496
## 6 6 2 52.64841
## 7 7 3 64.15909
## 8 8 4 45.20604
## 9 9 1 89.68948
## 10 10 2 47.22426
## 11 11 3 58.35302
## 12 12 4 69.63506
reshape(transform(df,obs=ave(1:nrow(df),df$treatment,FUN=seq_along)),dir='w',idvar='obs',timevar='treatment');
## obs effect.1 effect.2 effect.3 effect.4
## 1 1 32.06171 53.69698 81.75691 27.39249
## 5 2 48.39496 52.64841 64.15909 45.20604
## 9 3 89.68948 47.22426 58.35302 69.63506通过一些演绎的逆向工程,我想我已经能够破解你的数据是什么样的格式,根据你贴在评论中的内容。下面演示了我为综合数据提供的解决方案,我认为这与您自己的解决方案非常相似:
set.seed(33);
df <- data.frame(OBS=1:12, Treatment=c('PyrI','PyrII','Keto','Placebo')[rep(1:4,each=3)], Flaking=as.integer(rnorm(12,16,2)) );
df;
## OBS Treatment Flaking
## 1 1 PyrI 15
## 2 2 PyrI 15
## 3 3 PyrI 18
## 4 4 PyrII 15
## 5 5 PyrII 11
## 6 6 PyrII 16
## 7 7 Keto 14
## 8 8 Keto 17
## 9 9 Keto 17
## 10 10 Placebo 13
## 11 11 Placebo 16
## 12 12 Placebo 15
reshape(transform(df,OBS=ave(1:nrow(df),df$Treatment,FUN=seq_along)),dir='w',idvar='OBS',timevar='Treatment');
## OBS Flaking.PyrI Flaking.PyrII Flaking.Keto Flaking.Placebo
## 1 1 15 15 14 13
## 2 2 15 11 17 16
## 3 3 18 16 17 15发布于 2015-05-12 03:10:19
我会做这样的事
你的数据:
df <- data.frame(group = rep(LETTERS[1:4], 4), scores = runif(16))假设您的数据是两列,一列指定组,另一列中有值。下面的第一个部分所做的是统计每个组的出现情况,然后相应地传播数据。
library(tidyr)
library(dplyr)
df %>% group_by(group) %>% mutate(count = row_number()) %>% spread(group, scores) 结果:
count A B C D
1 1 0.6211185 0.2278333 0.68751500 0.03104363
2 2 0.4507366 0.1834150 0.05700584 0.18217047
3 3 0.3411344 0.4382062 0.23057716 0.85572707
4 4 0.8514964 0.8386036 0.95319578 0.76257128您的值会有所不同,因为这些值是随机生成的,而我忘了使用set.seed。如果每个组的病例数不均衡,它将用NAs填充空单元格。
发布于 2015-05-12 05:51:11
我的印象是,您试图像描述的这里那样计算虚拟编码列。如果将处理声明为“因子”,则大多数回归函数都会自动执行此操作。
如果需要手动执行此操作,心理库将提供函数虚拟代码(看见)。
示例(从@jalapic窃取的测试数据):
df <- data.frame(group = rep(LETTERS[1:4], 4), scores = runif(16))
library(psych)
cbind(dummy.code(df$group), df)给予:
A B C D group scores
1 1 0 0 0 A 0.73130714
2 0 1 0 0 B 0.60615966
3 0 0 1 0 C 0.74046980
4 0 0 0 1 D 0.13636377
5 1 0 0 0 A 0.33951820
6 0 1 0 0 B 0.95789481
7 0 0 1 0 C 0.26756629
8 0 0 0 1 D 0.71264870
9 1 0 0 0 A 0.87482811
10 0 1 0 0 B 0.69434779
11 0 0 1 0 C 0.92821292
12 0 0 0 1 D 0.70466255
13 1 0 0 0 A 0.30458528
14 0 1 0 0 B 0.90092407
15 0 0 1 0 C 0.77997403
16 0 0 0 1 D 0.05661558https://stackoverflow.com/questions/30180970
复制相似问题