Как выполнить антисортировку данных с помощью R - PullRequest
0 голосов
/ 01 февраля 2019

Я не уверен, как назвать его, но если у меня есть список значений, таких как:

set.seed(2084)
vals = round(runif(12, 1, 3))

[1] 2 3 2 2 1 1 3 2 1 2 2 2

и я сортирую это у меня есть:

[1] 1 1 1 2 2 2 2 2 2 2 3 3

Но я хочу получить что-то вроде альтернативной сортировки (взять 1-2-3 и повторите):

1 2 3 1 2 3 1 2 2 2 2 2

Но проблема в том, что есть 7 двойок, и они следуют за списком, а не чередуются между другими значениями,Я предпочел бы получить что-то вроде:

1 2 2 3 1 2 2 2 1 2 2 3

или

1 2 2 3 1 2 2 3 12 2 2

Как я могу проиндексировать его, чтобы получить наиболее равномерно распределенные значения этого порядка "роста и обрезки"?

Чтобы дать некоторое представление о моей идее.Из множества N уникальных значений (здесь 3) нам нужно распределить каждое из них как можно дальше друг от друга (и от границ этого вектора).Таким образом, в то время как у нас есть 1 и 10 слотов, мы можем поместить их как в этом шаблоне:

= 1 = = = 1 = = = 1

или

= =1 = = 1 = = 1 =

Это верно, если другие номера не имеют соответствующих позиций в этом списке.Мы можем добавить тройки:

= 3 1 = = 1 = 3 1 =

Теперь у нас есть только две пары для заполнения. У них не будет идеальных позиций.Я думаю, что было бы лучше начать с числа с наиболее распространенными значениями.

Я хотел бы прояснить и описать некоторый алгоритм, но я чувствую, что это обратный эффект.

# EDIT # Я думаю, для больших наборов данных тема могла бы стоять "какравномерно распределить значения в заданном векторе, используя R ".Возможно, это может быть безопасным выходом из этой ситуации, если это приведет к недоразумению.Но здесь я не хочу иметь 2 номера, кроме того, пока доступно 5 слотов.

Для 1 2 2 3 4 есть альтернатива, например, 1 2 3 4 2.

РЕДАКТИРОВАТЬ 2

Я нашел функцию для 2 значений -это полу-решение, но идея работает.Я думаю, что это будет итеративно для более чем 2 значений, но, возможно, я ошибаюсь.

Это не очень элегантно

antisort <- function(vals) {
  l = length(unique(vals))
  mx = names(which.max(table(vals)))
  mn = names(which.min(table(vals)))
  mxn = max(table(vals))
  indx = round(seq(from = 1, to = length(vals), length.out = mxn))
  vec = NULL
  for (i in indx) {
    vec[i] <- mx
  }
  vec[which(is.na(vec))] <- mn
  return(vec)
}

data:

set.seed(2201)
vals = round(runif(12, 1, 2))

Выполнить:

antisort(vals)

Результат (независимо от того, что он струнный)

"2" "1" "2" "1" "2" "2" "1" "2" "1"" 2 "" 1 "" 2 "

Ответы [ 2 ]

0 голосов
/ 02 февраля 2019

Вот возможный эвристический подход:

set.seed(2084)
maxn <- 3
vals = round(runif(12, 1, maxn)) #integral values

#result vector
v <- rep(NA_character_, length(vals))

#tabulate frequencies and sort in descending order
lens <- sort(table(vals), decreasing=TRUE)

#going through each distinct integral values, starting with the longest one
for (x in names(lens)) {
    #cut the result vector into roughly lens[x] number of parts
    idx <- cut(seq_along(v), breaks=lens[x])

    #fill the first NA with the current integral value
    split(v, idx) <- lapply(split(v, idx), function(subv) {
        subv[which(is.na(subv))[1L]] <- x
        subv
    })
}

#split the vector into maxn number of parts and sort each group
#the hardest part is probably how many parts to split into, which is defaulted
#to maximum of integral values in the original vector
lapply(split(v, cut(seq_along(v), breaks=maxn, labels=1L:maxn)), sort)

вывод:

$`1`
[1] "1" "2" "2" "3"

$`2`
[1] "1" "2" "2" "2"

$`3`
[1] "1" "2" "2" "3"

Соответствующая ссылка: https://cs.stackexchange.com/questions/29709/algorithm-to-distribute-items-evenly

0 голосов
/ 01 февраля 2019

Одним из них может быть то, что вы искали:

rep_len(unique(vals), length(vals))

или

rep_len(sort(unique(vals)), length(vals))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...