将变量名称向量中的Inf / -Inf值替换为类似名称的变量向量(substr / grep / gsub)中的值

时间:2018-10-15 18:09:01

标签: r data.table

我目前很困惑地编写一些有效的代码。我有一个变量向量(med.vars),这些变量被年内全球中位数转化。有时全局中位数为0,这会创建logger值,我想用预先转换的变量值(vars)代替。我无法弄清楚如何使用某些类型的%(name)s函数或带有Inf/-Infdata.table 'dat[,:=lapply(.SD), .SDcols=med.vars]等的for循环来有效地做到这一点。

get()

实际上,这些向量是我用noquotes()dat<-data.table(v1=c(2,10,7),v2=c(5,6,5),v3=c(10,15,20),v1.med=c(1,Inf,5),v2.med=c(5,6,5),v3.med=c(-Inf,2,3)) vars<-c("v1","v2","v3") med.vars<-c("v1.med","v2.med","v3.med") v1 v2 v3 v1.med v2.med v3.med 1: 2 5 10 1 5 -Inf 2: 10 6 15 Inf 6 2 3: 7 5 20 5 5 3 中提取的50多个变量,并使用names(dat)创建了预先转换的变量名的第二向量。

我想高效地执行

grep()

对于每个元素gsub(".med","",med.vars)及其对应的元素dat[v1.med==Inf | v1.med==-Inf, v1.med:=v1] dat[v3.med==Inf | v3.med==-Inf, v3.med:=v3] ,这样得到的med.vars[i]为:

vars[i]

谢谢您的时间

2 个答案:

答案 0 :(得分:3)

OP提到效率,所以也许改用长期形式。然后可以使用标准语法:

DT = melt(dat, meas=list(vars, med.vars), value.name=c("var", "med"))

DT[!is.finite(med), med := sign(med)*var]

   variable var med
1:        1   2   1
2:        1  10  10
3:        1   7   5
4:        2   5   5
5:        2   6   6
6:        2   5   5
7:        3  10 -10
8:        3  15   2
9:        3  20   3

答案 1 :(得分:2)

由于这些是对应的列,我们可以使用Map

dat[, (med.vars) := Map(function(x, y) ifelse(is.finite(y), y,
            x * sign(y)), .SD[, vars, with = FALSE], 
              .SD[, med.vars, with = FALSE])]

dat
#   v1 v2 v3 v1.med v2.med v3.med
#1:  2  5 10      1      5    -10
#2: 10  6 15     10      6      2
#3:  7  5 20      5      5      3

或者另一个选择是set,方法是使用for循环遍历各列

for(j in seq_along(vars)) {
  i1 <- !is.finite(dat[[med.vars[j]]])
  v1 <- dat[[vars[j]]]
  v2 <- dat[[med.vars[j]]]

  set(dat, i = which(i1), j = med.vars[j], value = sign(v2[i1]) * v1[i1])

 }

这也可以在base R上(在data.frame上完成)

i1 <- !sapply(dat[med.vars], is.finite)
dat[med.vars][i1] <- dat[vars][i1] * sign(dat[med.vars][i1])