对R中字符串的dplyr友好位操作
我需要对包含位字符串的tible列执行逐位操作。例如,我希望能够做一些像对R中字符串的dplyr友好位操作,r,dplyr,R,Dplyr,我需要对包含位字符串的tible列执行逐位操作。例如,我希望能够做一些像 ds <- tibble(Id=1:2, X1=c("001", "011"), X2=c("101", "110")) mutate(ds, X1andX2 = magic.AND(X1,X2)) mutate(ds, X1Int = bitStrToInt(X1), X2Int = bitStrToInt(X2)) %>% mutate(X1andX2 = intToBitStr(bitwAnd(X1In
ds <- tibble(Id=1:2, X1=c("001", "011"), X2=c("101", "110"))
mutate(ds, X1andX2 = magic.AND(X1,X2))
mutate(ds, X1Int = bitStrToInt(X1), X2Int = bitStrToInt(X2)) %>%
mutate(X1andX2 = intToBitStr(bitwAnd(X1Int, X2Int), bitN=4)) %>%
select(-X1Int, -X2Int)
dsPackagebitops
使这些操作变得简单
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
库(位操作)
我放弃了一个简单的解决方案。根据康拉德·鲁道夫的建议,我编写了两个转换函数。第一个灵感来自于
它可能不是很有效,我还没有测试过它。如果结果太慢,我将用Perl编写所有内容。如何001
和101
给出001
?元素方面,即0&1=>0,0&0=>0,1&1=>1如果您追求性能,第一个明显的问题是为什么要将位存储在字符串中。而是将它们存储在位向量(=整数)中,并执行真正的位运算。@Sotos…根据传统的位运算规则。@Konrad Rudolph,我想到了这一点,但我必须保持它的用户友好性。如果其他人打开数据文件进行快速查看,他们需要能够轻松区分“0101000”(多个0)和“1110111”(多个1)。级别2:使此dplyr友好。抱歉,我提供了一个不好的示例。这种方法适用于三位字符串,但对较长的字符串无效。此外,我可能需要对很长的字符串进行操作,而位运算将所有内容转换为32位整数。我把问题扩大到更清楚。
# A tibble: 2 x 4
Id X1 X2 X1andX2
<int> <chr> <chr> <chr>
1 1 0101 1110 0100
2 2 1110 0110 0110
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
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)