在同一列中划分因子级别以获取新的数据框

时间:2019-06-16 13:15:02

标签: r

我有一个数据框,看起来像下面的示例(这里的数据框包含针对每个回合,条件和处理的两个模拟):

df <- data.frame(Sim=c(1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2),Round=c(1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2),Condition=c('A1','A1','A2','A2','A1','A1','A2','A2','B1','B1','B2','B2','B1','B1','B2','B2','A1','A1','A2','A2','A1','A1','A2','A2','B1','B1','B2','B2','B1','B1','B2','B2'),Treatment=c(1,1,1,1,2,2,2,2,1,1,1,1,2,2,2,2,1,1,1,1,2,2,2,2,1,1,1,1,2,2,2,2),Output=c(3,2.5,2.1,1.9,2.8,2.3,2.0,1.6,2.6,2.7,1.3,1.2,2.4,2.3,1,1.1,2,1.3,1.3,0.9,2,2.1,2.1,1.2,2,1.7,1.2,1,2,1.3,0.5,0.4))

条件包含四个级别:A1,A2,B1,B2。

现在,我想操纵此数据框,以便获得A2在A1上针对每个模拟,回合,条件产生的 Output 减少量(%)(1-(A2 / A1) B1(1-(B2 / B1)上的B2也是如此。

我们应该获得与此类似的新dtaframe(此处的“新输出”不是基于数据帧):

Round    New condition  Treatment   Newoutput
1        1-(A2/A1)      1           0.3
1        1-(A2/A1)      1           0.24
...
1        1-(B2/B1)      2           0.5
1        1-(B2/B1)      2           0.56
...
2        1-(A2/A1)      1           0.43
2        1-(A2/A1)      1           0.23
...
2        1-(B2/B1)      1           0.4
2        1-(B2/B1)      1           0.5
...

我一直在尝试split原始数据帧,但是不确定如何处理它。我还尝试通过使用transform直接在数据框上进行操作。到目前为止没有成功。

在此先感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

我们可以首先在splitOutput Condition,然后交替选择12的值,并使用{{1 }}

mapply

或者如果您希望将它们作为一个矢量直接输入

lst <- with(df, split(Output, Condition))
mapply(function(x, y) 1-(y/x), lst[c(TRUE, FALSE)], lst[c(FALSE, TRUE)])

#             A1        B1
#[1,]  0.3000000 0.5000000
#[2,]  0.2400000 0.5555556
#[3,]  0.2857143 0.5833333
#[4,]  0.3043478 0.5217391
#[5,]  0.3500000 0.4000000
#[6,]  0.3076923 0.4117647
#[7,] -0.0500000 0.7500000
#[8,]  0.4285714 0.6923077

如果数据框的顺序不正确,则可以先排列它们,然后使用上面的

unname(1 - (unlist(lst[c(FALSE, TRUE)])/unlist(lst[c(TRUE, FALSE)])))
#[1]  0.3000000  0.2400000  0.2857143  0.3043478  0.3500000  0.3076923 -0.0500000  
#     0.4285714  0.5000000 0.5555556  0.5833333  0.5217391  0.4000000  0.4117647  
#     0.7500000  0.6923077

或者,如果水平不固定,则可以手动重新排列

df <- df[order(df$Condition), ]

如果还有更多级别,您可以做

df <- df[order(match(df$Condition, c("A1", "A2", "B1", "B2", "C1", "C2"))), ]