1
votes

I have a column in a dataframe consisting of a 8 bit bitmask. I want to 'explode' this to 8 new columns in my data frame. The bitmask is defined as:

mask <- c('term1'=1,'term2'=2,'term3'=4,'term4'=8,...) #etc

by the end, I want 8 new columns in my dataframe named term1 through term8 with a TRUE/FALSE value noting whether the bit was set. For example, with a 3 bit mask:

id   bitmask
 a         1
 b         4
 c         5

would be come:

id   bitmask   term1   term2   term3
 a         1    TRUE   FALSE   FALSE
 b         4   FALSE   FALSE    TRUE
 c         5    TRUE    FALSE    TRUE

I've gotten as far as writing the function that creates the bitmask column values:

addl <- as.data.frame(sapply(data$bitmask, function(x) bitwAnd(x,mask) > 0))

But I'm obviously doing something wrong because when I try to see the result using head(addl) it just hangs. I haven't even gotten to the point of cbind() or setting the column names. Any help understanding what I'm doing wrong would be greatly appreciated!

2
try using := to create new columns - Gary Weissman
Gary, thank you for the suggestion. I feel a bit silly asking this, but I looked up operators in R and I didn't see := anywhere. ?:= from RStudio yielded nothing as well? - Alexander David
It is from data.table package. And I think it is better to use ??":=" to search about this function (if data.table is already installed). - user3710546
I take back what I said. See below. - Gary Weissman
you can pass parameters to your function FUN in sapply by passing them as parameters in the same function call as a parameter in sapply - Gary Weissman

2 Answers

3
votes

In base R, set up the data:

mask <- c('term1'=1,'term2'=2,'term3'=4)
df <- data.frame(id = c(letters[1:3]), bitmask = c(1,4,5))

cbind(df, sapply(mask, bitwAnd, df$bitmask) > 0)

#   id bitmask term1 term2 term3
# 1  a       1  TRUE FALSE FALSE
# 2  b       4 FALSE FALSE  TRUE
# 3  c       5  TRUE FALSE  TRUE

Or with data.table can do:

require(data.table)
dt <- as.data.frame(df)

data.table(dt, dt[,sapply(mask, bitwAnd, bitmask)] > 0)

#    id bitmask term1 term2 term3
# 1:  a       1  TRUE FALSE FALSE
# 2:  b       4 FALSE FALSE  TRUE
# 3:  c       5  TRUE FALSE  TRUE
2
votes

Base R:

mask <- c('term1'=1,'term2'=2,'term3'=4,'term4'=8)

dat <- data.frame(id=letters[1:3], bitmask=c(1, 4, 5), stringsAsFactors=FALSE)

cbind(dat, do.call(rbind, lapply(dat$bitmask, function(x) {
  setNames(rbind.data.frame(bitwAnd(x, mask)>0), names(mask))
})))

##   id bitmask term1 term2 term3 term4
## 1  a       1  TRUE FALSE FALSE FALSE
## 2  b       4 FALSE FALSE  TRUE FALSE
## 3  c       5  TRUE FALSE  TRUE FALSE

But Gary's updated answer is way better.