Как получить второе наиболее встречающееся значение (и наименее встречающееся значение) в каждой строке в R - PullRequest
0 голосов
/ 19 октября 2018

Для каждой строки в моем фрейме данных я хочу найти второе по величине встречающееся значение, а также наименее встречающееся значение.Как я могу это сделать?

Df:

label v1 v2 v3 v4 v5 v6
5     3  3  3  6  6  8
5     7  1  1  1  7  0
5     3  5  6  6  6  5

Я хочу рассмотреть все столбцы, кроме 'label'

Ожидаемый результат:

second largest occuring     least occuring
6                           8
7                           0
5                           3

Изменить: я обновил пример после того, как ответ был принят, чтобы сделать его менее запутанным

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Еще одно решение dplyr, которое немного более читабельно и обрабатывает ошибки для NA и случаев, когда существует множество вхождений второго по величине.Это решение также позволяет выбирать несколько столбцов с использованием языка dplyr.

library(dplyr)

dat = read.table(text = 'label v1 v2 v3 v4 v5 v6
5     3  3  3  2  2  1
5     2  1  1  1  2  0
5     3  5  6  6  6  5', header = T)

second_largest <- function(x,na.rm = TRUE) {
  if(na.rm) { x <- na.omit(x) } # omit NA values
  second_largest <- x[dense_rank(x) == 2] # return all values where the rank is equal to 2nd largest
  second_largest <- max(second_largest) # keep one value out of all the second largest, or NA
  return(second_largest)
}

df <- dat %>%
  mutate(
    second_largest = select(., v1:v6) %>% apply(1, second_largest,na.rm = TRUE), # apply second_largest func to every row
    min = select(., v1:v6) %>% apply(1,min,na.rm = TRUE) # apply min to every row
  ) 

#   label v1 v2 v3 v4 v5 v6 second_largest min
# 1     5  3  3  3  2  2  1              2   1
# 2     5  2  1  1  1  2  0              1   0
# 3     5  3  5  6  6  6  5              5   3

Несколько замечаний.

В операторе применения 1 указывает, что функция должна применяться к строкам.

Обновление

Если вычтобы получить значение второго по частоте числа, вы просто подключаете новую функцию для этого.

second_most_frequent <- function(x, is_numeric = TRUE) {
  out <- x %>%
    table() %>% # Create a table of frequencies as characters
    as.data.frame(stringsAsFactors = FALSE) %>%
    arrange(desc(Freq)) %>% # Arrange with frequency descending
    .[,1] %>% # Select the first column
    .[2] # select the second most frequent (WARNING: Doesn't check for ties)
  if(is_numeric){ out <- as.numeric(out) }
  return(out)
}

df <- df %>%
  mutate(
    second_most_freq = select(., v1:v6) %>% apply(1,second_most_frequent,is_numeric = TRUE)
  )

#   label v1 v2 v3 v4 v5 v6 second_largest min second_most_freq
# 1     5  3  3  3  2  2  1              2   1                2
# 2     5  2  1  1  1  2  0              1   0                2
# 3     5  3  5  6  6  6  5              5   3                5
0 голосов
/ 19 октября 2018

A dplyr решение:

df %>%
  rowid_to_column() %>%
  gather(var, val, -label, -rowid) %>%
  group_by(rowid, val) %>%
  tally() %>%
  summarise(second_largest_occuring = val[dense_rank(n) == 2],
            least_occuring = val[n == min(n)]) %>%
  ungroup() %>%
  select(-rowid)

# A tibble: 3 x 2
  second_largest_occuring least_occuring
                    <int>          <int>
1                       2              1
2                       2              0
3                       5              3

Данные:

df <- read.table(text = "label v1 v2 v3 v4 v5 v6
5     3  3  3  2  2  1
                 5     2  1  1  1  2  0
                 5     3  5  6  6  6  5", header= TRUE)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...