2016-06-24 2 views
2

연속적인 1 또는 2를 0으로 대체하려고합니다. 나는 R 베스트 프랙티스에 실제로 맞지 않는 루프를 제외하고는 이것을 수행하는 방법을 생각할 수 없다. 누구든지 "R 방식"으로 이것을 수행하는 방법에 대한 팁을 제공 할 수 있습니까?문자열에서 반복되는 값을 0으로 대체하십시오.

set.seed(42) 
temp<-sample(c(2,1),10,replace=T) 
df<-data.frame(vals=temp) 

예를 들어 결과 :

vals goal 
1  1 1 
2  1 0 
3  2 2 
4  1 1 
5  1 0 
6  1 0 
7  1 0 
8  2 2 
9  1 1 
10 1 0 

내 (비 작동) 시도가 필요한 경우

#get all strings with 1 
match <- gregexpr("1+", as.vector(df$vals)) 
#iterate over all matches and create vectors that replace consecutive values with 0 based on the length of match.length 
lapply(match,function(y){ 
    sapply(attr(y, "match.length"),function(x)rep(0,x)) 
}) 

그냥 또 다른 예를 추가 :

val goal 
1 1 
2 2 
2 0 
2 0 
1 1 
1 0 
1 0 

답변

3

우리는 확인 diff을 사용할 수 있습니다 이전 : 유사

df$goal<- df$vals 
df$goal[-1] <- ifelse(diff(df$vals)==0, 0, df$vals[-1]) 


df 
    vals out 
1  1 1 
2  1 0 
3  2 2 
4  1 1 
5  1 0 
6  1 0 
7  1 0 
8  2 2 
9  1 1 
10 1 0 

또는,

,536,913,632 10
df$goal[which(diff(df$vals) == 0) +1L] <- 0 
+2

또는 비슷하게,'df $ vals [(diff (df $ vals) == 0) + 1L] <- 0'. 이 질문에 대한 답을 자유롭게 편집하십시오 –

+0

평소 사용하는'rle'이나 제'seqle'에 대한 플러그를 넣을 것입니다. –

3

사용 rleid을 함께,623,210 :

library(data.table) 
df$goal <- df$vals 
df$goal[duplicated(rleid(df$goal))] <- 0 
df 
    vals goal 
1  1 1 
2  1 0 
3  2 2 
4  1 1 
5  1 0 
6  1 0 
7  1 0 
8  2 2 
9  1 1 
10 1 0 

또는 느껴지 valsvals을 비교하고 조건을 만족하는 경우 두 번째 예를 들어, 제로를 할당 : 하나 개의 값이 같은 경우

df$goal <- df$vals 
df$goal[df$vals == shift(df$vals)] <- 0 

    val goal 
1 1 1 
2 2 2 
3 2 0 
4 2 0 
5 1 1 
6 1 0 
7 1 0 
+0

데이터를 사용하는 경우.어쨌든'setDT (df) [, 목표 : = vals] [중복 (rleid (vals)), 목표 : = 0]' –

+0

@docendodiscimus 그래. 우리도 그렇게 할 수 있습니다. 좋은 구문. – Psidom

1

우리는

rle(df$vals) 
#Run Length Encoding 
#lengths: int [1:5] 2 1 4 1 2 
# values : num [1:5] 1 2 1 2 1 

list 2의를 반환는 코드를 분할하는 것이 더있을 수 있습니다, 어떻게 rle 작품을 이해하기 base R.

df$vals *!duplicated(inverse.rle(within.list(rle(df$vals), 
            values <-seq_along(values)))) 
#[1] 1 0 2 1 0 0 0 2 1 0 

에서 rle을 사용할 수 있습니다 요소 '즉,'길이 '와'값 'lengths은 반복되는 각 반복 요소의 길이를가집니다. list이므로 within.list을 사용하여 '값'을 '값'의 순서로 변경합니다. 우리가 inverse.rle를 사용하는 경우

within.list(rle(df$vals), values <-seq_along(values)) 
# Run Length Encoding 
# lengths: int [1:5] 2 1 4 1 2 
# values : int [1:5] 1 2 3 4 5 ## changed 

,이 '길이'우리는 duplicated 요소의 논리적 인 벡터를 사용하여 얻을

inverse.rle(within.list(rle(df$vals), values <-seq_along(values))) 
#[1] 1 1 2 3 3 3 3 4 5 5 

,

duplicated(inverse.rle(within.list(rle(df$vals), values <-seq_along(values)))) 
#[1] FALSE TRUE FALSE FALSE TRUE TRUE TRUE FALSE FALSE TRUE 

부정에 의해 '값'복제의 벡터를 반환 (!) FALSE/TRUETRUE/FALSE으로 변경하십시오.

!duplicated(inverse.rle(within.list(rle(df$vals), values <-seq_along(values)))) 
#[1] TRUE FALSE TRUE TRUE FALSE FALSE FALSE TRUE TRUE FALSE 

TRUE/FALSE1/0로 저장됩니다. 따라서 1/0을 곱하면 0에 해당하는 요소는 0을 반환합니다.

+0

이것은 훌륭하게 작동했지만, 나중에'inverse.rle'을 사용하고'rle'을 사용하는 것을 이해하지 못합니다. 좀 더 설명해 주시겠습니까? – Rilcon42

+1

환상적입니다. 고마워요! – Rilcon42

관련 문제