对R中字符串的dplyr友好的按位运算

时间:2016-07-26 14:20:23

标签: r dplyr

我需要对包含位字符串的tibble列执行按位运算。例如,我希望能够做类似

的事情
ds <- tibble(Id=1:2, X1=c("001", "011"), X2=c("101", "110"))
mutate(ds, X1andX2 = magic.AND(X1,X2))

获取

# A tibble: 2 x 4
      Id    X1    X2   X1andX2
    <int> <chr> <chr>   <chr>
1     1    001   101     001
2     2    011   110     010

我正在操作不是特别大的数据集(~50k行),但我必须多次执行此操作。所以,我正在寻找或多或少有效和简单的东西。

由于我必须运行许多连接和组操作,我更喜欢与dplyr兼容的方法。

编辑抱歉,上面的示例不是很好,因为三位字符串在转换为整数和填充0之后会产生看起来像三位字符串的结果(请参阅Sotos&#39; s回答几乎有效)。此外,很高兴看到长字符串的解决方案,即超过32位。这是一个更好的例子。

ds <- tibble(Id=1:2, X1=c("0101", "1110"), X2=c("1110", "0110"))

输出

# A tibble: 2 x 4
      Id    X1    X2   X1andX2
    <int> <chr> <chr>   <chr>
1     1    0101  1110    0100
2     2    1110  0110    0110

2 个答案:

答案 0 :(得分:1)

bitops使这些操作变得简单,

library(bitops)
ds$X1_X2 <- sprintf('%03d', bitAnd(ds$X1, ds$X2))
ds
# A tibble: 2 x 4
#     Id    X1    X2 X1_X2
#  <int> <chr> <chr> <chr>
#1     1   001   101   001
#2     2   011   110   010

答案 1 :(得分:0)

我放弃了一个简单的解决方案。按照Konrad Rudolph的建议,我写了两个转换函数。第一个是受 atesghnagfbvgfr's answer to another question的启发。

intToBitStr <- Vectorize(function(x, bitN) {
    i <- 0
    v <- integer(bitN)
    while(x > 0) {
        v[bitN - i] <- x %% 2
        x <- x %/% 2
        i <- i + 1 
    }
    return(paste0(v, collapse=""))
}, c("x"), USE.NAMES = F)

bitStrToInt <- Vectorize(function(x) {
    v <- rev(as.integer(strsplit(x, "")[[1]]))
    acc <- 0
    for (i in 1:length(v)) {
        acc <- acc + v[i] * 2^(i - 1)
    }
    return(acc)
}, USE.NAMES = F)

使用这两个函数,解决方案就像

mutate(ds, X1Int = bitStrToInt(X1), X2Int = bitStrToInt(X2)) %>%
mutate(X1andX2 = intToBitStr(bitwAnd(X1Int, X2Int), bitN=4)) %>%
select(-X1Int, -X2Int)

可能效率不高,我还没有测试过。如果它太慢了,我只会用Perl编写所有内容。