2016-07-26 4 views
1

비트 문자열이 포함 된 tibble 열에서 비트 연산을 수행해야합니다. 예를 들어, 난 (~ 50K 행) 특히 대형하지 않은 데이터 세트에서 작동하고문자열에 dplyr 친화적 인 비트 연산 R

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

를 얻기 위해

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

처럼 뭔가를 할 수 있도록하고 싶습니다하지만 난에이 이 작업을 여러 번 수행하십시오. 그래서 나는 다소 효율적이거나 단순한 것을 찾고 있습니다.

많은 조인과 그룹 작업을 실행해야하므로 dplyr와 호환되는 접근 방식을 선호합니다.

편집 : 세 개의 비트 문자열 (거의 작동 Sotos의 답변을 참조) 0으로 정수와 패딩으로 캐스팅 후 3 비트 스트링과 같이 결과를로 죄송합니다, 위의 예제는 매우 좋지 않다. 또한 긴 문자열 (32 비트 이상)에 대한 해결책을 찾는 것이 좋습니다. 여기에 더 좋은 예가 있습니다.

ds <- tibble(Id=1:2, X1=c("0101", "1110"), X2=c("1110", "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 
+2

'001'과 '101'은 어떻게 '001'을 제공합니까? – Sotos

+0

Element-wise, 즉 0 & 1 => 0, 0 & 0 => 0, 1 & 1 => 1 – rbrisk

+1

퍼포먼스가 끝나면 확실한 첫 번째 질문은 비트를 문자열에 저장하는 이유입니다. 대신 비트 벡터 (= 정수)로 저장하고 진정한 비트 연산을 수행하십시오. –

답변

1

패키지. 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로 모든 것을 쓸 것이다.

+0

레벨 2 :이 dplyr을 친숙하게 만드십시오. – zx8754

+0

죄송합니다. 잘못된 예를 제공했습니다. 이 방법은 3 비트 문자열에서 작동하지만 긴 문자열에서는 실패합니다. 또한, BitOps가 모든 것을 32 비트 정수로 변환하는 동안 매우 긴 문자열을 처리해야 할 수도 있습니다. 나는이 질문을보다 명확하게 확대했다. – rbrisk

+0

최대한 빨리 수정합니다. – Sotos

0

bitops 이러한 작업을 쉽게

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