Abdul Rahman K
Abdul Rahman K

Reputation: 664

Adding column to existing data table, using formula from one column and operand data from other column

I'm a beginner in R, I have the following data, where table is like this:

dt
    fct X Y Z   fct1 Q
 1:   a 2 1 a:a    a a:a:2
 2:   b 4 2 b:b    b b:b:4
 3:   c 3 1 c:c    c c:c:3
 4:   d 2 2 d:d    d d:d:2
 5:   c 5 1 c:c    c c:c:5
 6:   d 4 2 d:d    d d:d:4
 7:   a 7 1 a:a    a a:a:7
 8:   b 2 2 b:b    b b:b:2
 9:   c 9 1 c:c    c c:c:9
10:   a 1 2 a:a    a a:a:1
11:   b 4 1 b:b    b b:b:4
12:   c 2 2 c:c    c c:c:2
13:   b 5 1 b:b    b b:b:5
14:   c 4 2 c:c    c c:c:4
15:   d 2 1 d:d    d d:d:2`

and, have a List like this:

flist
$a
[1] "X + Y"
$b
[1] "X - Y"
$c
[1] "X * Y"
$d
[1] "paste0(Z,':',fct)"

Since flist has an entry for a, whenever an entry a in fct column is seen, then the corresponding formula from the list needs to be executed, using the values of Y and Z column, and applied to Column XY.

I tried solution like this:

within(dt2, XY <- eval(parse(text=flist['a']))), which works with the clearly seen constraint, which is, it can only be applied with the formula for a.

However, this: within(dt2, XY <- eval(parse(text=flist[fct]))) doesn't work. Even this: within(dt2, XY <- eval(parse(text=eval(parse(text=flist[fct])))))) doesn't work.

Use case is that, looking into fct Column, its variable should be used to look up the formula in flist, and then applied with the Data in X and Y and applied to XY.

I kindly look forward for help.

Upvotes: 2

Views: 51

Answers (1)

akrun
akrun

Reputation: 886948

We can use the data.table methods by specifying the logical condition in 'i' (assuming that 'fct' is character class and assign (:=) the evaluated string from the list element (flist$a) to create the new column 'XY'

dt[fct == names(flist), XY := eval(parse(text=flist$a))]
dt
#    fct X Y   Z fct1     Q XY
# 1:   a 2 1 a:a    a a:a:2  3
# 2:   b 4 2 b:b    b b:b:4 NA
# 3:   c 3 1 c:c    c c:c:3 NA
# 4:   d 2 2 d:d    d d:d:2 NA
# 5:   c 5 1 c:c    c c:c:5 NA
# 6:   d 4 2 d:d    d d:d:4 NA
# 7:   a 7 1 a:a    a a:a:7  8
# 8:   b 2 2 b:b    b b:b:2 NA
# 9:   c 9 1 c:c    c c:c:9 NA
#10:   a 1 2 a:a    a a:a:1  3
#11:   b 4 1 b:b    b b:b:4 NA
#12:   c 2 2 c:c    c c:c:2 NA
#13:   b 5 1 b:b    b b:b:5 NA
#14:   c 4 2 c:c    c c:c:4 NA
#15:   d 2 1 d:d    d d:d:2 NA

Update

If there are multiple elements in 'flist'

for(j in seq_along(flist)){
  dt[fct == names(flist)[j], XY := eval(parse(text= flist[[j]]))][]
}

dt
#    fct X Y   Z fct1     Q XY
# 1:   a 2 1 a:a    a a:a:2  3
# 2:   b 4 2 b:b    b b:b:4  2
# 3:   c 3 1 c:c    c c:c:3  3
# 4:   d 2 2 d:d    d d:d:2 NA
# 5:   c 5 1 c:c    c c:c:5  5
# 6:   d 4 2 d:d    d d:d:4 NA
# 7:   a 7 1 a:a    a a:a:7  8
# 8:   b 2 2 b:b    b b:b:2  0
# 9:   c 9 1 c:c    c c:c:9  9
#10:   a 1 2 a:a    a a:a:1  3
#11:   b 4 1 b:b    b b:b:4  3
#12:   c 2 2 c:c    c c:c:2  4
#13:   b 5 1 b:b    b b:b:5  4
#14:   c 4 2 c:c    c c:c:4  8
#15:   d 2 1 d:d    d d:d:2 NA

data

flist <- list(a= "X + Y")
#updated flist
flist <- list(a = "X + Y", b = "X - Y", c = "X * Y")

Upvotes: 2

Related Questions