case_when在一个实例中工作,而不是另一个

时间:2019-05-20 02:52:41

标签: r dplyr

我正在尝试按季度汇总数据。但是,这些宿舍不遵循正常的宿舍。我的宿舍从十二月开始。

我可以使用以下代码将数据细分为四分之一:

require(tidyverse)

# generate dummy data
data <- data.frame(value = runif(12, min = 10000, max = 12000),
                   month = 1:12,
                   stringsAsFactors = F)

qtr <- data %>% 
  mutate(quarter = case_when(month == 1:3 ~ 1,
                             month == 4:6 ~ 2,
                             month == 7:9 ~ 3,
                             month == 9:12 ~ 4))

预期结果:

       value month quarter
1  11959.56     1       1
2  10389.29     2       1
3  10731.31     3       1
4  10433.61     4       2
5  11969.98     5       2
6  10240.25     6       2
7  11415.40     7       3
8  10942.18     8       3
9  11114.58     9       3
10 11109.37    10       4
11 11448.45    11       4
12 10940.48    12       4

现在,我尝试更改季度细目分类,以便季度从12月开始,例如。

qtr <- data %>% 
      mutate(quarter = case_when(month == 1:2 ~ 1,
                             month == 3:5 ~ 2,
                             month == 6:8 ~ 3,
                             month == 9:11 ~ 4,
                             month == 12 ~ 1))

我得到:

      value month quarter
1  11959.56     1       1
2  10389.29     2       1
3  10731.31     3      NA
4  10433.61     4      NA
5  11969.98     5      NA
6  10240.25     6      NA
7  11415.40     7      NA
8  10942.18     8      NA
9  11114.58     9      NA
10 11109.37    10      NA
11 11448.45    11      NA
12 10940.48    12       1

我为什么要得到NA?

1 个答案:

答案 0 :(得分:2)

简短答案:

使用%in%代替==,因为您要比较多个值

library(dplyr)

data %>% 
   mutate(quarter = case_when(month %in% c(1:2, 12) ~ 1,
                              month %in% 3:5 ~ 2,
                              month %in% 6:8 ~ 3,
                              month %in% 9:11 ~ 4))

#      value month quarter
#1  11216.52     1       1
#2  10767.37     2       1
#3  10631.57     3       2
#4  11906.64     4       2
#5  11575.19     5       2
#6  11403.56     6       3
#7  10315.16     7       3
#8  11631.13     8       3
#9  11083.61     9       4
#10 11755.59    10       4
#11 10247.68    11       4
#12 10485.54    12       1

长期回答

第一个选项由于选择的数字和R中的回收属性而偶然“起作用”。

例如,考虑这种情况

1:10 == 4:6
# [1] FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE
  

警告信息:   在1:10 == 4:6中:     较长的物体长度不是较短的物体长度的倍数

这里实际发生的是4:6被回收并变成

a1 <- rep(4:6, length.out = 10)
a1
#[1] 4 5 6 4 5 6 4 5 6 4

现在将其与

进行比较
a2 <- 1:10
a2
# [1]  1  2  3  4  5  6  7  8  9 10

逐个元素。检查4:6a1

中位置a2的值
a1[4:6]
#[1] 4 5 6
a2[4:6]
#[1] 4 5 6

它们都是相同的,因此,在TRUE中比较它们时,您会在这些位置收到case_when值。对于其他情况,在您的第一次尝试中也会发生同样的情况,并且您认为它是有效的。

即使您在此处或此处更改一个数字,也无法按预期工作。例如,

data %>% 
  mutate(quarter = case_when(month == 1:2 ~ 1,
                             month == 3:6 ~ 2,
                             month == 7:9 ~ 3,
                             month == 9:12 ~ 4))

#      value month quarter
#1  11436.83     1       1
#2  10524.27     2       1
#3  10110.57     3      NA
#4  11755.68     4      NA
#5  10757.70     5      NA
#6  10203.56     6      NA
#7  11346.90     7       3
#8  10308.79     8       3
#9  10328.54     9       3
#10 10732.88    10       4
#11 11150.69    11       4
#12 10990.28    12       4

对于第二种情况,3:5被回收并按元素进行比较

a3 <- rep(3:5, length.out = 10)

a2 == a3
# [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE

由于没有匹配项,因此所有值均为FALSE,并且您在NA中得到case_when