Заменить повторяющиеся значения на 0

#r

#r

Вопрос:

Я хочу заменить повторяющиеся значения в моем фрейме данных на 0. Допускается некоторое количество повторений.

 a<-c(1,2,3,4,4,4,5,5,5,5,5,9,9,150,220,220)
 

В этом случае допустимое количество повторений равно, скажем, 4. Ожидаемое решение должно выглядеть следующим образом:

 a_new<-c(1,2,3,4,4,4,0,0,0,0,0,9,9,150,220,220)
 

Более 4 раз повторяющиеся значения заменяются на 0.

Используя rle

 b<-rle(a)
 

Я могу определить количество повторений

 Run Length Encoding
  lengths: int [1:8] 1 1 1 3 5 2 1 2
  values : num [1:8] 1 2 3 4 5 9 150 220
 

И заменить его на 0

 b$values[b$lengths>4]<-0

Run Length Encoding
  lengths: int [1:8] 1 1 1 3 5 2 1 2
  values : num [1:8] 1 2 3 0 0 9 150 220
 

Вопрос в том, как вставить повторения, в данном случае 0, обратно в данные.

Ответ №1:

Вы можете использовать inverse.rle

 a_new<-c(1,2,3,4,4,4,0,0,0,0,0,9,9,150,220,220)

b <- rle(a_new)

b$values[b$lengths>4]<-0

inverse.rle(b)

[1]   1   2   3   4   4   4   0   0   0   0   0   9   9 150 220 220
 

Комментарии:

1. Inverse.rle именно то, что я искал

Ответ №2:

Вы также можете добиться этого в одной строке с помощью

 with(rle(a), rep(values * (lengths <= 4), lengths))
# [1]   1   2   3   4   4   4   0   0   0   0   0   9   9 150 220 220
 

так что мы работаем внутри rle(a) и непосредственно выполняем модификацию inverse.rle :

 inverse.rle
# function (x, ...) 
# {
#     if (is.null(le <- x$lengths) || is.null(v <- x$values) || 
#         length(le) != length(v)) 
#         stop("invalid 'rle' structure")
#     rep.int(v, le) # The same except for le <= 4
# }
# <bytecode: 0x10470b4a8>
# <environment: namespace:base>
 

Ответ №3:

Другой способ через ave ,

 a[ave(a, a, FUN = length) > 4] <- 0
a
#[1]   1   2   3   4   4   4   0   0   0   0   0   9   9 150 220 220
 

Комментарии:

1. rle я думаю, это важно. Для этого a<-c(1, 1, 2,3,4,4,4,5,5,5,5,5,9,9,150,1, 1, 1) он неправильно преобразует 1 в 0.

2. На самом деле не ясно. OP говорит, что повторяется, но затем пытается с ним работать rle . Я оставлю это до тех пор, пока они не прояснят

Ответ №4:

Также возможна:

 (a != rle(a)$values[rle(a)$lengths > 4]) * a

 [1]   1   2   3   4   4   4   0   0   0   0   0   9   9 150 220 220
 

Ответ №5:

С помощью rleid

 library(data.table)
data.table(a)[, a1 := if(.N >4) 0 else a, rleid(a)]$a1
#[1]   1   2   3   4   4   4   0   0   0   0   0   9   9 150 220 220