2015-10-05 50 views
2

我在dplyr中遇到了意外的行为。我试图用一个变量的值来加权数据集中的所有变量。这是膳食数据,每份营养值。服务的重量是已知的,我希望分析每克食物的价值,而不是每份食物。dplyr中mutate_each的意外行为 - 变异中使用的变异突变了

服务重量是数据集中的第十个数值变量。前九个转换正确。权重变量也被正确设置为1.随后的变量保持不变(或可能被1除)。这不是预料!

这个问题可以通过在数据框的末尾创建一个新的变量来解决,它保存了服务重量变量的值。它也可以通过将权重变量留在mutate语句中来解决,但我选择不这样做,因为它提供了有用的检查。

下面是一个简单的例子,让我的观点: -

library(dplyr) 
a <- letters[1:6] 
x1 <- rep(1,6);x2 <- rep(2,6);x3 <- rep(3,6) 
x4 <- rep(4,6);x5 <- rep(5,6);x6 <- rep(6,6) 
#I want to divide each variable by one of the variables - Two examples 
d <- data.frame(a,x1,x2,x3,x4,x5,x6) 
d %>% mutate_each(funs(Weight = ./x3),x1:x6) #Unexpected! 
d %>% mutate_each(funs(Weight = ./x4),x1:x6) #Unexpected! 

输出:

a  x1  x2 x3 x4 x5 x6 
1 a 0.3333333 0.6666667 1 4 5 6 
2 b 0.3333333 0.6666667 1 4 5 6 
3 c 0.3333333 0.6666667 1 4 5 6 
4 d 0.3333333 0.6666667 1 4 5 6 
5 e 0.3333333 0.6666667 1 4 5 6 
6 f 0.3333333 0.6666667 1 4 5 6 

    a x1 x2 x3 x4 x5 x6 
1 a 0.25 0.5 0.75 1 5 6 
2 b 0.25 0.5 0.75 1 5 6 
3 c 0.25 0.5 0.75 1 5 6 
4 d 0.25 0.5 0.75 1 5 6 
5 e 0.25 0.5 0.75 1 5 6 
6 f 0.25 0.5 0.75 1 5 6 

解决方法:

#Make a new variable at the end of the data frame 
d$Three <- d$x3 
d$Four <- d$x4 

d %>% mutate_each(funs(Weight = ./Three),x1:x6) #Expected! 
d %>% mutate_each(funs(Weight = ./Four),x1:x6) #Expected! 

输出:

a  x1  x2 x3  x4  x5 x6 Three Four 
1 a 0.3333333 0.6666667 1 1.333333 1.666667 2  3 4 
2 b 0.3333333 0.6666667 1 1.333333 1.666667 2  3 4 
3 c 0.3333333 0.6666667 1 1.333333 1.666667 2  3 4 
4 d 0.3333333 0.6666667 1 1.333333 1.666667 2  3 4 
5 e 0.3333333 0.6666667 1 1.333333 1.666667 2  3 4 
6 f 0.3333333 0.6666667 1 1.333333 1.666667 2  3 4 

    a x1 x2 x3 x4 x5 x6 Three Four 
1 a 0.25 0.5 0.75 1 1.25 1.5  3 4 
2 b 0.25 0.5 0.75 1 1.25 1.5  3 4 
3 c 0.25 0.5 0.75 1 1.25 1.5  3 4 
4 d 0.25 0.5 0.75 1 1.25 1.5  3 4 
5 e 0.25 0.5 0.75 1 1.25 1.5  3 4 
6 f 0.25 0.5 0.75 1 1.25 1.5  3 4 

考虑到dplyr允许您在创建和使用新变量时使用,这是有道理的。但是,对我而言,这种特定的行为是违反直觉的,也许是因为我总是认为突变是原子性的。在这种情况下,他们不是!

我想我现在可能已经回答了我原来的问题,但是我会在这里发布其他人被同样的行为咬伤。这有意义吗?我理解了正确的行为吗?

+1

我同意,这不是伟大的,总是有X1:5233依次修改。如果可以关闭,那会很好。 – Frank

+1

鉴于您已经回答了您自己的问题,您可以将其作为答案发布。然后其他人会一眼就看出问题已经解决。 –

+1

它看起来像一个错误。也许你应该报告它:https://github.com/hadley/dplyr/issues。请注意,如果不通过明确排除权重变量来创建新列,则可以避免此行为,例如。 'd%>%mutate_each(funs(权重= ./x3),x1:x6,-x3)' – scoa

回答

1

另一个解决方法是引用数据帧前面的变量d$x3。因为默认情况下它是适用于所有非分组变量,我们只需排除列-a避免由数除以一个因素,产生的NA:

d %>% mutate_each(funs(Weight = ./d$x3), -a) 

输出:

a  x1  x2 x3  x4  x5 x6 
1 a 0.3333333 0.6666667 1 1.333333 1.666667 2 
2 b 0.3333333 0.6666667 1 1.333333 1.666667 2 
3 c 0.3333333 0.6666667 1 1.333333 1.666667 2 
4 d 0.3333333 0.6666667 1 1.333333 1.666667 2 
5 e 0.3333333 0.6666667 1 1.333333 1.666667 2 
6 f 0.3333333 0.6666667 1 1.333333 1.666667 2 

如果我们组,那么我们需要使用scoa指定的方法,排除该变量,因为d$x3会产生错误。请注意,因为我们正在按变量a进行分组,所以我们不需要这次排除它。

d %>% group_by(a) %>% mutate_each(funs(Weight = ./x3), -x3) 

输出:

Source: local data frame [6 x 7] 
Groups: a [6] 

     a  x1  x2 x3  x4  x5 x6 
    (fctr)  (dbl)  (dbl) (dbl) (dbl) (dbl) (dbl) 
1  a 0.3333333 0.6666667  3 1.333333 1.666667  2 
2  b 0.3333333 0.6666667  3 1.333333 1.666667  2 
3  c 0.3333333 0.6666667  3 1.333333 1.666667  2 
4  d 0.3333333 0.6666667  3 1.333333 1.666667  2 
5  e 0.3333333 0.6666667  3 1.333333 1.666667  2 
6  f 0.3333333 0.6666667  3 1.333333 1.666667  2