2017-11-11 103 views
2
library(data.table) 
library(lubridate) 

x1 <- c(20090101, "2009-01-02", "2009 01 03", "2009-1-4", 
     "2009-1, 5", "Created on 2009 1 6", "200901 !!! 07") 

dt2 <- data.table(id = c(1,1,1,2,2,2,2), date1 = ymd(x1), charval = c("aa","vv","ss","a","b","c","d")) 

    id  date1 charval 
1: 1 2009-01-01  aa 
2: 1 2009-01-02  vv 
3: 1 2009-01-03  ss 
4: 2 2009-01-04  a 
5: 2 2009-01-05  b 
6: 2 2009-01-06  c 
7: 2 2009-01-07  d 

我用下面的代码通过ID分组:[R崩溃多行到1行使用特定的功能,日期和字符列

dt3 <- dt2[, Map(function(x,y) ifelse(x != "paste", get(x)(y, na.rm = TRUE), paste(y, sep = ";")), 
           setNames(c("mean", "paste"), names(.SD)), .SD), by = id] 

得到的东西是这样的:

id  date1 charval 
1: 1 2009-01-02  aa;vv;ss 
2: 2 2009-01-05  a;b;c;d 

但实际上我看到下一个结果:

id date1 charval 
1: 1 NA  aa 
2: 2 NA  a 

1)我不明白为什么粘贴不工作 2)我不明白为什么平均值(日期1)不工作 因为例如下面的代码工作正常:

mean(dt2$date1) 
[1] "2009-01-04" 

回答

1

为什么我们要经过Map目前尚不清楚和get。通过 'ID' 分组后,得到 '日期1' 和paste的 'charval' 在一起的mean

dt2[, .(date1 = mean(date1), charval = toString(charval)), id] 
# id  date1 charval 
#1: 1 2009-01-02 aa, vv, ss 
#2: 2 2009-01-05 a, b, c, d 

注:toStringpaste(..., collapse=', ')

dt2[, .(date1 = mean(date1), charval = paste(charval, collapse=";")), id] 
# id  date1 charval 
#1: 1 2009-01-02 aa;vv;ss 
#2: 2 2009-01-05 a;b;c;d 

由于OP的问题是关于Map使用get拨打mean。这似乎是触发

如果(!is.numeric(x)的& &!is.complex(x)的& &!is.logical(X)){ 警告(“的说法是不是数字或逻辑:返回NA“) 回报(NA_real_)

并且当它发现‘日期1’是Date类虽然被存储为numeric返回NA。一种选择是指定envir中的get

另一个问题是使用ifelse。这是更好地使用if/else,因为只有两个元素

dt2[, Map(function(x, y) if(x != "paste") get(x, envir = parent.frame())(y, na.rm = TRUE) 
    else paste(y, collapse=':'), setNames(c("mean", "paste"), names(.SD)), .SD), by = id] 
# id  date1 charval 
#1: 1 2009-01-02 aa:vv:ss 
#2: 2 2009-01-05 a:b:c:d 

get是棘手的一种,如果指定正确的环境,它按预期工作

get("mean")(dt2$date1) 
#[1] "2009-01-04" 

或代替if/else到“粘贴”字符串,我们可以查看列class,如果它是character,则执行paste或返回mean

dt2[, Map(function(x, y) if(is.character(y)) get(x)(y, collapse=":") 
    else get(x, envir = parent.frame())(y, na.rm = TRUE), 
    setNames(c("mean", "paste"), names(.SD)), .SD), by = id] 
# id  date1 charval 
#1: 1 2009-01-02 aa:vv:ss 
#2: 2 2009-01-05 a:b:c:d 

请注意,最好使用第一种方法而不用麻烦

相关问题