在另一个变量的基础上与其他变量一起创建新变量

时间:2019-05-28 16:05:06

标签: r

我有4个日期变量和1个分组变量。根据分组变量中的值,需要将日期放入新变量中。 我的数据如下:(https://www.dropbox.com/s/wlfv89qc1jzwfgk/vb.JPG

我想根据group的值创建一个新变量。当组为A时,我需要date1;当组为B时,我需要date2,依此类推。

这是我使用的代码:

+

此代码给我警告消息:

(如果if(tabel $ group == 1){:   条件的长度> 1,并且只会使用第一个元素

2 个答案:

答案 0 :(得分:0)

您需要按行执行此操作...一个选项是使用嵌套的ifelse()

newvar=ifelse(tabel$group=='A',tabel$date1,
              ifelse(tabel$group=='B',tabel$date2,
                     ifelse(tabel$group=='C',tabel$date3,tabel$date4))))

答案 1 :(得分:0)

我确信之前已经多次询问并回答了这个问题,但是我没有找到很好的副本。

嵌套ifelse()并不总是最好的解决方案。编写,阅读和维护很多括号很麻烦。此外,ifelse()可能会意外更改结果的类型,例如类Date

所以,我想发布一些替代方法

使用match()进行子设置

这个人使用了一个特殊的事实,即第一个字母“ A”对应于第一个日期列date1,依此类推。因此,它可能通常不适用:

indices <- matrix(c(seq.int(nrow(tabel)), match(tabel$group, LETTERS[1:4])), ncol = 2)
newvar <- tabel[, -1][indices]
newvar
 [1] "2011-01-01" "2011-01-02" "2011-01-03" "2012-02-04" "2012-02-05" "2012-02-06" "2013-03-07" "2013-03-08" "2013-03-09"
[10] "2014-04-10" "2014-04-11" "2014-04-12"

用于子设置的indices(行号,列号)是:

      [,1] [,2]
 [1,]    1    1
 [2,]    2    1
 [3,]    3    1
 [4,]    4    2
 [5,]    5    2
 [6,]    6    2
 [7,]    7    3
 [8,]    8    3
 [9,]    9    3
[10,]   10    4
[11,]   11    4
[12,]   12    4

tabel[, -1]省略了第一列(group)。

case_when()

这是来自if_else()包的多个dplyr语句的向量化版本。

newvar <- dplyr::case_when(
  tabel$group == "A" ~ tabel$date1,
  tabel$group == "B" ~ tabel$date2,
  tabel$group == "C" ~ tabel$date3,
  tabel$group == "D" ~ tabel$date4)

library(dplyr)
newvar <- tabel %>% 
  transmute(value = case_when(group == "A" ~ date1,
                              group == "B" ~ date2,
                              group == "C" ~ date3,
                              group == "D" ~ date4)) %>% 
  pull(value)

使用data.table联接查找表

查找表将group与列名之间的关系视为数据,因此易于创建和维护。另一方面,tabel必须从宽格式改成长格式,然后才能与lookup结合使用:

library(data.table)
lookup <- data.table(group = LETTERS[1:4], variable = paste0("date", 1:4))
newvar <- melt(setDT(tabel), id.vars = "group")[lookup, on = .(group, variable)]$value

lookup
   group variable
1:     A    date1
2:     B    date2
3:     C    date3
4:     D    date4

重塑的长格式为

melt(setDT(tabel), id.vars = "group")
    group variable      value
 1:     A    date1 2011-01-01
 2:     A    date1 2011-01-02
 3:     A    date1 2011-01-03
 4:     B    date1 2011-01-04
 5:     B    date1 2011-01-05
 6:     B    date1 2011-01-06
 7:     C    date1 2011-01-07
 8:     C    date1 2011-01-08
 9:     C    date1 2011-01-09
10:     D    date1 2011-01-10
11:     D    date1 2011-01-11
12:     D    date1 2011-01-12
13:     A    date2 2012-02-01
14:     A    date2 2012-02-02
15:     A    date2 2012-02-03
16:     B    date2 2012-02-04
17:     B    date2 2012-02-05
18:     B    date2 2012-02-06
19:     C    date2 2012-02-07
20:     C    date2 2012-02-08
21:     C    date2 2012-02-09
22:     D    date2 2012-02-10
23:     D    date2 2012-02-11
24:     D    date2 2012-02-12
25:     A    date3 2013-03-01
26:     A    date3 2013-03-02
27:     A    date3 2013-03-03
28:     B    date3 2013-03-04
29:     B    date3 2013-03-05
30:     B    date3 2013-03-06
31:     C    date3 2013-03-07
32:     C    date3 2013-03-08
33:     C    date3 2013-03-09
34:     D    date3 2013-03-10
35:     D    date3 2013-03-11
36:     D    date3 2013-03-12
37:     A    date4 2014-04-01
38:     A    date4 2014-04-02
39:     A    date4 2014-04-03
40:     B    date4 2014-04-04
41:     B    date4 2014-04-05
42:     B    date4 2014-04-06
43:     C    date4 2014-04-07
44:     C    date4 2014-04-08
45:     C    date4 2014-04-09
46:     D    date4 2014-04-10
47:     D    date4 2014-04-11
48:     D    date4 2014-04-12
    group variable      value

使用dplyrtidyr结合查找表

library(dplyr)
library(tidyr)
lookup <- tibble(group = LETTERS[1:4], key = paste0("date", 1:4))
newvar <- tabel %>% 
  gather(key, value, -group) %>% 
  inner_join(lookup) %>% 
  pull(value)

这与上面的工作原理相同:创建查找表,从宽格式改成长格式并合并。 pull()返回一个简单的结果向量。

可复制的数据

tabel <- data.frame(group = rep(LETTERS[1:4], each = 3L),
                    date1 = as.Date("2011-01-01") + 0:11,
                    date2 = as.Date("2012-02-01") + 0:11,
                    date3 = as.Date("2013-03-01") + 0:11,
                    date4 = as.Date("2014-04-01") + 0:11)
tabel
    group      date1      date2      date3      date4
 1:     A 2011-01-01 2012-02-01 2013-03-01 2014-04-01
 2:     A 2011-01-02 2012-02-02 2013-03-02 2014-04-02
 3:     A 2011-01-03 2012-02-03 2013-03-03 2014-04-03
 4:     B 2011-01-04 2012-02-04 2013-03-04 2014-04-04
 5:     B 2011-01-05 2012-02-05 2013-03-05 2014-04-05
 6:     B 2011-01-06 2012-02-06 2013-03-06 2014-04-06
 7:     C 2011-01-07 2012-02-07 2013-03-07 2014-04-07
 8:     C 2011-01-08 2012-02-08 2013-03-08 2014-04-08
 9:     C 2011-01-09 2012-02-09 2013-03-09 2014-04-09
10:     D 2011-01-10 2012-02-10 2013-03-10 2014-04-10
11:     D 2011-01-11 2012-02-11 2013-03-11 2014-04-11
12:     D 2011-01-12 2012-02-12 2013-03-12 2014-04-12