2016-06-24 18 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 

あるいは、同様に、

df$goal[which(diff(df$vals) == 0) +1L] <- 0 
+2

また、同様に、 'df $ vals [(diff(df $ vals)== 0)+ 1L] < - 0'です。これをあなたの答えに自由に編集してください –

+0

私は通常のプラグイン「rle」または私自身の「seqle」に入れます。 –

3

使用rleidduplicated

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 

が2のlistを返し、どのよう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を使用してループし、 '値'を '値'のシーケンスとして変更します。

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 

我々はinverse.rleを使用している場合、これは、我々が使用して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

関連する問題