Измените 20 процентов определенного значения в каждом столбце на число

#r

Вопрос:

У меня есть фрейм данных, подобный этому:

 start = 0
end = 2

v1<-round ( runif ( n=20, min=start, max=end ))
v2<-round ( runif ( n=20, min=start, max=end ))
v3<-round ( runif ( n=20, min=start, max=end ))

df <- data.frame(v1,v2,v3)
 

Я хочу, чтобы 20 процентов каждого числа в каждом столбце было изменено на 5. Например, если у меня есть 10 чисел «1» в первом столбце, я хочу, чтобы 20 процентов этого числа «1» было преобразовано в «5».

Как я могу решить эту проблему в программе R?

Спасибо, что ответили!

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

1. Просто случайным образом заменить заданный процент на какое-то число? Кроме того, как вы считаете «десять чисел в первой колонке»?

Ответ №1:

Я создал простую функцию, которую вы можете использовать внутри apply (или purrr::map или purrr::map_df функции)

 # reproducibility
set.seed(4242)
start = 0
end = 2

v1 <-round(runif(n = 20, min = start, max = end))
v2 <-round(runif(n = 20, min = start, max = end))
v3 <-round(runif(n = 20, min = start, max = end))

df1 <- data.frame(v1,v2,v3)

# replace the value with 5 for the chosen number in the vectors
change_number <- function(x, number) {
  x <- replace(x, sample(which(x == number), 
                         length(which(x == number)) * 0.2, 
                         replace = FALSE), 5)
  x
  }

# reproducibility
set.seed(42) 

df2 <- apply(df1, 2, change_number, number = 1)
# if you need it returned as a data.frame instead of a matrix run the following line
# df2 <- data.frame(df2)
df2

     v1 v2 v3
 [1,]  2  0  1
 [2,]  5  5  0
 [3,]  0  0  0
 [4,]  1  1  1
 [5,]  1  1  1
 [6,]  2  1  1
 [7,]  2  2  1
 [8,]  0  5  1
 [9,]  1  1  1
[10,]  2  1  0
[11,]  0  1  2
[12,]  1  0  2
[13,]  0  2  0
[14,]  2  1  1
[15,]  2  0  2
[16,]  2  0  5
[17,]  0  2  0
[18,]  1  1  5
[19,]  1  1  2
[20,]  0  1  1
 

Ответ №2:

Это звучит так, как будто вы хотите, чтобы 20% каждого числа в каждом столбце было заменено на 5. В этом случае попробуйте воспользоваться этой функцией replaceNumbers . Аргумент repl= определяет замену в вашем случае 5 . Если вы установите at_least_one= TRUE это значение , по крайней мере одно из тех чисел, где 20% их встречаемости меньше единицы, также будет заменено.

 replaceNumbers <- function(x, repl, at_least_one=FALSE) {
  sapply(unique(x), function(z) {
    w <- which(x == z)
    l <- length(w)
    if (l < 3 amp; at_least_one) s <- 1
    else s <- l*.2
    x[sample(w, s)] <<- repl
  })
  return(x)
}

set.seed(42)  ## for sake of reproducibility
res <- as.data.frame(lapply(df, replaceNumbers, repl=5, at_least_one=FALSE))
 

Сравнение результатов с оригиналом:

 data.frame(df, res)
#    v1 v2 v3 v1.1 v2.1 v3.1
# 1   2  2  1    5    5    1
# 2   2  0  1    2    0    5
# 3   1  2  0    5    2    0
# 4   2  2  2    2    2    5
# 5   1  0  1    1    5    1
# 6   1  1  2    1    1    2
# 7   1  1  2    1    1    2
# 8   0  2  1    0    2    1
# 9   1  1  2    5    1    2
# 10  1  2  1    1    2    1
# 11  1  1  1    1    5    1
# 12  1  2  1    1    2    1
# 13  2  1  1    2    1    1
# 14  1  1  2    1    1    2
# 15  1  0  0    1    0    0
# 16  2  2  1    2    2    1
# 17  2  0  1    2    0    5
# 18  0  0  0    0    0    0
# 19  1  2  1    1    2    1
# 20  1  1  1    1    1    1
 

Данные:

 df <- structure(list(v1 = c(2, 2, 1, 2, 1, 1, 1, 0, 1, 1, 1, 1, 2, 
1, 1, 2, 2, 0, 1, 1), v2 = c(2, 0, 2, 2, 0, 1, 1, 2, 1, 2, 1, 
2, 1, 1, 0, 2, 0, 0, 2, 1), v3 = c(1, 1, 0, 2, 1, 2, 2, 1, 2, 
1, 1, 1, 1, 2, 0, 1, 1, 0, 1, 1)), class = "data.frame", row.names = c(NA, 
-20L))
 

Ответ №3:

Итак, вы хотите, чтобы 20% «1» в кадре данных стали 5, правильно?

Сначала давайте спросим позиции каждого числа 1, используя which() . Затем возьмите 20% от then и, наконец, присвоите этим позициям значение «5».

 df1s = which(df==1)
df1s = sample(df1s,length(df1s)*0.2,replace=F)
df[df1s] = 5