2

I have two data tables with the same dimensions- one filled with numbers, the other with symbols which can be positive or negative, ex.

A = data.table(colOne = c(-1, 3, 4), 
           colTwo = c(1, 0, -1));

B = data.table(colOne = c("a","b","-c"), 
           colTwo = c("d","-e","f"));

and need to multiply both elementwise:

resultMatrix = data.table(colOne = c("-a","3b","-4c"), 
                          colTwo = c("d","0","-f"))

("-e*0" would also be acceptable instead of "0" in colTwo of the result) and am unsure how to do this without going through loops which costs a lot of time for larger tables. What is the proper way to go about doing this?

Jacob H
  • 4,317
  • 2
  • 32
  • 39
Dement
  • 85
  • 6
  • Are you using the `ryacas` package? I never have, but it was the first hit for "R symbolic math" and it looks very promising. – Gregor Thomas Nov 06 '15 at 22:18
  • No- but I have heard about it and will definitely give it a try if no quick answer turns up. Thanks for the tip. – Dement Nov 06 '15 at 22:21

2 Answers2

1

This will get you close: All that would remain is moving the minus signs to the LHS of the strings:

mapply(paste, A, B, MoreArgs=list(sep='*') )
     colOne colTwo
[1,] "-1*a" "1*d" 
[2,] "3*b"  "0*-e"
[3,] "4*-c" "-1*f"

Using sub finalizes this effort with your example for the second part:

> res[] <- sapply(res , function(x) sub("(.*)([-])(.*)", "\\2\\1\\3", x) )
> res
     colOne colTwo
[1,] "-1*a" "1*d" 
[2,] "3*b"  "-0*e"
[3,] "-4*c" "-1*f"

Before I composed this I looked up a couple of earlier questions that I thought might be similar: How to represent polynomials with numeric vectors in R and https://stackoverflow.com/questions/16862801/trouble-mapping-vectors-arrays-into-polynomials-that-return-vector, but they did not seem to answer this particular question that involved several varialbe names, although I do specifically recommend looking at the 'mpoly'-package.

Community
  • 1
  • 1
IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • Very interesting. "-1*a", "-0*e", etc. should turn into "-a", "0" in an existing, subsequent "postprocessing" step, so both answers should work and now it's just a matter of checking which works fastest. Thanks @TheTime, BondedDust – Dement Nov 07 '15 at 07:20
1

This could be a chance to use gsubfn. It works like gsub except you can apply a function to the replacement. The function f here captures all digits and '-' in the first group, characters in the second. Then coerces to numeric, taking advantage of the fact that the only failing case is a trailing "-".

library(gsubfn)
## Function to pass to gsubfn (use backref to get reference to orignal string)
## x is original string, y is first group (numbers), z is last (characters)
f <- function(x, y, z) {
    n <- as.numeric(y)
    if(is.na(n)) n <- as.numeric(substr(y, 1, nchar(y)-1))*-1  # case: [-]\\d+-
    if (n == 0) return( '0' )
    if (n == 1) return( z )
    if (n == -1) return( paste0("-", z) )
    return( paste0(n, z) )
}

A[, lapply(1:ncol(A), function(i) suppressWarnings(
    gsubfn('([-\\d]+)(.*)', f, paste0(A[[i]], B[[i]]), backref=2))) ]
#     V1 V2
# 1:  -a  d
# 2:  3b  0
# 3: -4c -f
Rorschach
  • 31,301
  • 5
  • 78
  • 129