0

sorry for the duplicate, but for some reason, the answer shown here doesn't work for me. I´ve checked and the data table I'm working with is of character nature.

That's my data table

> dt <- data.table(V1 = c("4", "1", "0", "3"), V2 = c("0/1", "0/1", "1/2", "3/4"))

> dt
   V1  V2
1:  4 0/1
2:  1 0/1
3:  0 1/2
4:  3 3/4

> class(dt)
[1] "data.table" "data.frame"
> class(dt$V2)
[1] "character"

As you see I modeled the second column so as to have elements exclusively in fraction format. I want to have the second column in decimal format, the first column as a numeric rather than character & the final objective is to have the two columns summed up row-wise.

As I try turning it to decimal however it has no effect whatsoever on my dt - see it for yourselves

> FractionToDecimal <- function(x) {
+   eval(parse(text=as.character(x)))
+        x
+ }
> sapply(dt$V2, FractionToDecimal)
  0/1   0/1   1/2   3/4 
"0/1" "0/1" "1/2" "3/4" 
> FractionToDecimal(dt$V2)
[1] "0/1" "0/1" "1/2" "3/4"

The other approach I used, also doesn't work out

> dt %>% mutate(V2 = eval(parse(text = V2)))
  V1   V2
1  4 0.75
2  1 0.75
3  0 0.75
4  3 0.75

It just repeats the wrong result all over.

Does someone know where the problem lies?

If someone also knows how to have both columns turned into numeric/integer format afterward, it would also be of help!!

Thank you!!

mnal
  • 47
  • 5
  • The problem results from how you defined `FractionToDecimal()`. The `x` is redundant. – Darren Tsai May 15 '20 at 09:41
  • I´ve thought that that could be the case, so I've also tried out without, but still it didnt work.. Thanks for the tip tho, I always print the result at the end - will change that from now on – mnal May 15 '20 at 09:45
  • I mean just delete the `x` at the last line of `FractionToDecimal()`, and `sapply()` will work. It works for me. – Darren Tsai May 15 '20 at 09:54

3 Answers3

1

Use sapply.

dt$V2 <- sapply(dt$V2, function(x) eval(parse(text=x)))
dt
#   V1   V2
# 1  4 0.00
# 2  1 0.00
# 3  0 0.50
# 4  3 0.75
jay.sf
  • 60,139
  • 8
  • 53
  • 110
  • Thank you, jay.sf - it works! I dont understand though, why applying it directly works but using a function doesn't? wasn't it supposed to be the same thing? – mnal May 15 '20 at 09:25
  • 1
    I'm not 100% sure, but `parse` reads the vector "line by line", which is probably the reason that just it's last line is `eval`uated. Similar to non-vectorized, hence `sapply`. – jay.sf May 15 '20 at 09:31
1

Your function works but you are not changing x in the function and returning an unchanged x.

So either return output of eval + parse directly

FractionToDecimal <- function(x) eval(parse(text=x))
sapply(dt$V2, FractionToDecimal, USE.NAMES = FALSE)
#[1] 0.00 0.00 0.50 0.75

Or store the result in x and return the changed x.

FractionToDecimal <- function(x) {
   x <- eval(parse(text=x))
   x
}

sapply(dt$V2, FractionToDecimal, USE.NAMES = FALSE)
#[1] 0.00 0.00 0.50 0.75
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • Wow, I cant believe it. You're a 100% right! I've lost a lot of time, and cant believe that was the problem lol - thanks, ronak!! – mnal May 15 '20 at 09:50
0

Another option is to split with tstrsplit and divide

library(data.table)
dt[, do.call(`/`, tstrsplit(V2, "/", type.convert =TRUE))]
#[1] 0.00 0.00 0.50 0.75
akrun
  • 874,273
  • 37
  • 540
  • 662