#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