将列折叠为一个,删除NA,如果两者都不是NA则起作用

时间:2016-05-13 14:38:08

标签: r dplyr tidyr

我有一些关于xy中的分离的数据作为时间的函数。 只能在xy或两者(对角线,x==y)之间存在分隔:

data
#  Source: local data frame [307 x 4]

#             t0         t1             x             y
# 1   1449241093 1449241345            NA  4.085057e-02
# 2   1449241345 1449241537            NA  4.085057e-02
# ...
# 7   1449242375 1449242627  4.085057e-02            NA
# 8   1449242627 1449242818  4.085057e-02            NA
# ...
# 78  1449245524 1449246079  0.000000e+00  0.000000e+00
# 79  1449246079 1449246101 -2.042528e-01 -2.042528e-01
# ...

我想把它变成这种格式:

# Source: local data frame [307 x 4]

#            t0         t1 direction    separation
# 1  1449241093 1449241345         Y  4.085057e-02
# 2  1449241345 1449241537         Y  4.085057e-02
# ...
# 8  1449242627 1449242818         X  4.085057e-02
# 9  1449242818 1449242949         X  4.085057e-02
# ...
# 78  1449245524 1449246079        D  0.000000e+00
# 79  1449246079 1449246101        D  2.888571e-01
# ...

目前,我正在使用以下代码执行此操作:

data %>% mutate(direction=ifelse(is.na(x),"Y", ifelse(is.na(y),"X","D")),
                separation=ifelse(is.na(x),y, ifelse(is.na(y),x, sqrt(x**2 + y**2))) %>%
         select(data,-x,-y) 

我的问题:使用tidyr::gather()有更好的方法吗?

如果不是对角线情况,这将很好地工作,我得到多行(显然因为聚集没有被告知如何处理这些情况):

gather(data,direction,separation,x,y, na.rm=T) %>% arrange(t0)
# Source: local data frame [396 x 4]

#             t0         t1 direction    separation
# 1   1449241093 1449241345         y  4.085057e-02
# 2   1449241345 1449241537         y  4.085057e-02
# ...
# 7   1449242375 1449242627         x  4.085057e-02
# 8   1449242627 1449242818         x  4.085057e-02
# ...
# 77  1449245524 1449246079         x  0.000000e+00
# 78  1449245524 1449246079         y  0.000000e+00
# 79  1449246079 1449246101         x -2.042528e-01
# 80  1449246079 1449246101         y -2.042528e-01
# ...

基本上,我需要的是更高级的版本 How to collapse many records into one while removing NA values

1 个答案:

答案 0 :(得分:1)

我不确定这是否比明确ifelse更可取,但是你走了:

library(data.table)

setDT(df)[!is.na(x) | !is.na(y), .(t0, t1,
              direction  = c('X', 'Y', 'D')[((!is.na(.SD)) %*% c(1, 2))],
              separation = sqrt(rowSums(.SD^2, na.rm = T)))
          , .SDcols = x:y]

dplyr的翻译留给读者。