вернуть наиболее встречающееся символьное значение в r - PullRequest
3 голосов
/ 31 марта 2020

У меня есть:

df<-data.frame(group=c(1, 1, 1, 1, 2, 2, 2), 
               char=c("a", "b", "z", "a", "c", "c", "b"),
               want=c("a", "a", "a", "a", "c", "c", "c"))
df

  group char want
1     1    a    a
2     1    b    a
3     1    z    a
4     1    a    a
5     2    c    c
6     2    c    c
7     2    b    c

Я хочу вернуть значение, наиболее часто встречающееся в переменной char, по группам. Если есть способ адресации связей (т. Е. Если бы в группе 1 были два а и два б), то это также было бы идеально.

Спасибо

Ответы [ 4 ]

2 голосов
/ 31 марта 2020

Функция max.col имеет метод для работы со связями, так что вы можете превратить каждую группу в матрицу подсчетов и использовать max.col

df<-data.frame(group=c(1, 1, 1, 1, 2, 2, 2), 
               char=c("a", "b", "z", "a", "c", "c", "b"),
               want=c("a", "a", "a", "a", "c", "c", "c"))

df$want1 <- ave(df$char, df$group, FUN = function(x) {
  x <- t(table(x))
  # print(x)
  colnames(x)[max.col(x, ties.method = 'first')]
})

df

#   group char want want1
# 1     1    a    a     a
# 2     1    b    a     a
# 3     1    z    a     a
# 4     1    a    a     a
# 5     2    c    c     c
# 6     2    c    c     c
# 7     2    b    c     c

Для каждого уникального group, вы найдете индекс столбца с максимальным значением, затем берется имя столбца:

## group - 1
     a b c z
[1,] 2 1 0 1

## group - 2
     a b c z
[1,] 0 1 2 0
2 голосов
/ 31 марта 2020

Мы можем использовать функцию Mode из здесь , чтобы получить наиболее частое значение, выполнить группировку по «группам» и применить функцию к столбцу «char»

library(dplyr)
Mode <- function(x) {
   ux <- unique(x)
   tabl <- tabulate(match(x, ux))
   i1 <- tabl == max(tabl)
   stopifnot(sum(i1) == 1)
   toString(ux[i1])
   }

df %>%
   group_by(group) %>%
   mutate(want = Mode(char))
# A tibble: 7 x 3
# Groups:   group [2]
#  group char  want 
#  <dbl> <fct> <fct>
#1     1 a     a    
#2     1 b     a    
#3     1 z     a    
#4     1 a     a    
#5     2 c     c    
#6     2 c     c    
#7     2 b     c    

тестирование с галстуками

df$char[2] <- 'z'

df %>%
   group_by(group) %>%
   mutate(want = Mode(char))

Error: `mutate()` argument `want` errored.
ℹ `want` is `Mode(char)`.
ℹ The error occured in group 1: group = 1.
✖ sum(i1) == 1 is not TRUE
1 голос
/ 31 марта 2020

Вот 2 варианта использования data.table:

1) без использования by и переноса последнего наблюдения для NA_character_, поскольку nafill на данный момент не поддерживает класс символов.

library(data.table)
setDT(df)[order(group, -rowid(group, char)), 
    w1 := char[nafill(replace(.I, 1L + which(diff(group) == 0L), NA_integer_), "locf")]
]

Это должно быть быстрее, если у вас большой набор данных.

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

setDT(df)[order(group, -rowid(group, char)), w2 := char[1L], group]

output:

   group char want w
1:     1    a    a a
2:     1    b    a a
3:     1    z    a a
4:     1    a    a a
5:     2    c    c c
6:     2    c    c c
7:     2    b    c c
1 голос
/ 31 марта 2020

Один dplyr параметр может быть:

df %>%
 add_count(group, char) %>%
 group_by(group) %>%
 mutate(want = toString(unique(char[n == max(n)]))) %>%
 select(-n)

  group char  want 
  <dbl> <fct> <chr>
1     1 a     a    
2     1 b     a    
3     1 z     a    
4     1 a     a    
5     2 c     c    
6     2 c     c    
7     2 b     c 

Затем вы можете проверить наличие связей:

df %>%
 add_count(group, char) %>%
 group_by(group) %>%
 mutate(want = toString(unique(char[n == max(n)])),
        ties = grepl(",", want, fixed = TRUE)) %>%
 select(-n)

  group char  want  ties 
  <dbl> <fct> <chr> <lgl>
1     1 a     a     FALSE
2     1 z     a     FALSE
3     1 b     a     FALSE
4     1 a     a     FALSE
5     2 c     c     FALSE
6     2 c     c     FALSE
7     2 b     c     FALSE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...