Создать новый фрейм данных с условием в группе с R - PullRequest
0 голосов
/ 24 февраля 2019

Мне нужна помощь с использованием r фреймов данных.Вот кадр данных:

group   col1    col2    name
1       dog     40      canidae
1       dog     40      canidae
1       dog     40      canidae
1       dog     40      canidae
1       dog     40  
1       dog     40      canidae
1       dog     40      canidae
2       frog    85      dendrobatidae
2       frog    89      leptodactylidae
2       frog    89      leptodactylidae
2       frog    82      leptodactylidae
2       frog    89 
2       frog    81 
2       frog    89      dendrobatidae
3       horse   87      equidae1
3       donkey  76      equidae2
3       zebra   67      equidae3
4       bird    54      psittacidae
4       bird    56  
4       bird    34  
5       bear    67    
5       bear    54

То, что я хотел бы получить, это добавить столбец "consensus_name" и получить:

group col1   col2 name              consensus_name
1     dog    40   canidae           canidae
1     dog    40   canidae           canidae
1     dog    40                     canidae
1     dog    40   canidae           canidae
1     dog    40   canidae           canidae
2     frog   85   dendrobatidae     leptodactylidae
2     frog   89   leptodactylidae   leptodactylidae
2     frog   89   leptodactylidae   leptodactylidae
2     frog   82   leptodactylidae   leptodactylidae
2     frog   89                     leptodactylidae
2     frog   81                     leptodactylidae
2     frog   89   dendrobatidae     leptodactylidae
3     horse  87   equidae1          equidae3
3     donkey 76   equidae2          equidae3
3     zebra  67   equidae3          equidae3
4     bird   54   psittacidae       psittacidae
4     bird   56                     psittacidae
4     bird   34                     psittacidae
5     bear   67                     NA
5     bear   54                     NA

Для того, чтобы получить этот новый столбец для каждогогруппа, я получаю имя, которое является наиболее представительным в группе.

  • Для group1 есть 4 строки с именем 'canidae' и одна без нуля, поэтому для каждогоодин я пишу 'canidae' в столбце consensus_name

  • Для group2 есть 2 строки с именем 'dendrobatidae', 2 без знака и 3 строки с именем 'leptodactylidae' поэтому для каждого я пишу 'leptodactylidae' в столбце consensus_name.

  • Для group3 есть 3 строки с разными именами, так что нет единого мнения, Я получаю имя, которое в качестве самого низкого col2 числа, поэтому я пишу 'equidae3' в столбце consensus_name.

  • Для группы 4 только одна строка имеет информацию,так что это консенсус_имя group4, поэтому я пишу psittacidae в столбце consensus_name.

  • Для group5 информации нет, просто напишите NA в столбце consensus_name.

У кого-нибудь есть идеи сделать это с R?Спасибо за вашу помощь:)


Вот df:

structure(list(group = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L), col1 = structure(c(2L, 
2L, 2L, 2L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 3L, 6L, 
1L, 1L, 1L), .Label = c("bird", "dog", "donkey", "frog", "horse", 
"zebra"), class = "factor"), col2 = c(40L, 40L, 40L, 40L, 40L, 
40L, 40L, 85L, 89L, 89L, 82L, 89L, 81L, 89L, 87L, 76L, 67L, 54L, 
56L, 34L), name = structure(c(2L, 2L, 2L, 2L, 1L, 2L, 2L, 3L, 
7L, 7L, 7L, 1L, 1L, 3L, 4L, 5L, 6L, 8L, 1L, 1L), .Label = c("", 
"canidae", "dendrobatidae", "equidae1", "equidae2", "equidae3", 
"leptodactylidae", "psittacidae"), class = "factor")), class = "data.frame", row.names = c(NA, 
-20L))

реальный имеет около 50 000 строк.

Ответы [ 4 ]

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

Это еще одно dplyr решение.Он использует данные функции в пакете для упрощения некоторых команд, например, min(), max(), which().

df %>% filter(name != "") %>%
       group_by(group) %>%
       add_count(name) %>%
       top_n(1, n) %>%
       top_n(-1, col2) %>%
       distinct(consensus_name = name) %>%
       right_join(df)  # edit: not left_join()
  • top_n(1, n): эквивалентно filter(n == max(n))
  • top_n(-1, col2): эквивалентно filter(col2 == min(col2))

Примечание. Две top_n() команды не могут быть объединены с

filter(n == max(n) & col2 == min(col2))

, посколькудва логических утверждения являются последовательными, а не одновременными.


Вывод

   group consensus_name  col1    col2 name           
   <int> <fct>           <fct>  <int> <fct>          
 1     1 canidae         dog       40 canidae        
 2     1 canidae         dog       40 canidae        
 3     1 canidae         dog       40 canidae        
 4     1 canidae         dog       40 canidae        
 5     1 canidae         dog       40 ""             
 6     1 canidae         dog       40 canidae        
 7     1 canidae         dog       40 canidae        
 8     2 leptodactylidae frog      85 dendrobatidae  
 9     2 leptodactylidae frog      89 leptodactylidae
10     2 leptodactylidae frog      89 leptodactylidae
11     2 leptodactylidae frog      82 leptodactylidae
12     2 leptodactylidae frog      89 ""             
13     2 leptodactylidae frog      81 ""             
14     2 leptodactylidae frog      89 dendrobatidae  
15     3 equidae3        horse     87 equidae1       
16     3 equidae3        donkey    76 equidae2       
17     3 equidae3        zebra     67 equidae3       
18     4 psittacidae     bird      54 psittacidae    
19     4 psittacidae     bird      56 ""             
20     4 psittacidae     bird      34 ""
0 голосов
/ 24 февраля 2019

Мы можем использовать определение Mode из этого ответа (или любой упакованной версии режима, но, к сожалению, у R нет собственной) и использовать dplyr до mutateв соответствующих местах.

Mode <- function(x) {
  ux <- unique(x)
  ux[which.max(tabulate(match(x, ux)))]
}

library(dplyr)
df %>%
  group_by(group) %>%
  mutate(consensus_name=Mode(setdiff(name[order(col2)],"")))
# # A tibble: 20 x 5
# # Groups:   group [4]
#    group col1    col2 name            consensus_name 
#    <int> <fct>  <int> <fct>           <chr>          
#  1     1 dog       40 canidae         canidae        
#  2     1 dog       40 canidae         canidae        
#  3     1 dog       40 canidae         canidae        
#  4     1 dog       40 canidae         canidae        
#  5     1 dog       40 ""              canidae        
#  6     1 dog       40 canidae         canidae        
#  7     1 dog       40 canidae         canidae        
#  8     2 frog      85 dendrobatidae   leptodactylidae
#  9     2 frog      89 leptodactylidae leptodactylidae
# 10     2 frog      89 leptodactylidae leptodactylidae
# 11     2 frog      82 leptodactylidae leptodactylidae
# 12     2 frog      89 ""              leptodactylidae
# 13     2 frog      81 ""              leptodactylidae
# 14     2 frog      89 dendrobatidae   leptodactylidae
# 15     3 horse     87 equidae1        equidae3       
# 16     3 donkey    76 equidae2        equidae3       
# 17     3 zebra     67 equidae3        equidae3       
# 18     4 bird      54 psittacidae     psittacidae    
# 19     4 bird      56 ""              psittacidae    
# 20     4 bird      34 ""              psittacidae    
0 голосов
/ 24 февраля 2019

Я бы второй использовал функцию Mode.Кроме того, в качестве альтернативы dplyr вы можете быстро выполнять эти типы операций, используя пакет data.table:

library('data.table')
Mode <- function(x) {
  ux <- setdiff(unique(x), '')
  ux[which.max(tabulate(match(x, ux)))]
}

dt <- as.data.table(df)
dt[, consensus_name:= Mode(name), by = .(group)]

Вывод:

dt
   group   col1 col2            name  consensus_name
 1:     1    dog   40         canidae         canidae
 2:     1    dog   40         canidae         canidae
 3:     1    dog   40         canidae         canidae
 4:     1    dog   40         canidae         canidae
 5:     1    dog   40                         canidae
 6:     1    dog   40         canidae         canidae
 7:     1    dog   40         canidae         canidae
 8:     2   frog   85   dendrobatidae leptodactylidae
 9:     2   frog   89 leptodactylidae leptodactylidae
10:     2   frog   89 leptodactylidae leptodactylidae
11:     2   frog   82 leptodactylidae leptodactylidae
12:     2   frog   89                 leptodactylidae
13:     2   frog   81                 leptodactylidae
14:     2   frog   89   dendrobatidae leptodactylidae
15:     3  horse   87        equidae1        equidae1
16:     3 donkey   76        equidae2        equidae1
17:     3  zebra   67        equidae3        equidae1
18:     4   bird   54     psittacidae     psittacidae
19:     4   bird   56                     psittacidae
20:     4   bird   34                     psittacidae
0 голосов
/ 24 февраля 2019

Может пойти на:

library(dplyr)

df %>%
  add_count(group, name) %>% 
  group_by(group) %>%
  mutate(
    consensus_name = case_when(
      n_distinct(n[!name == ""]) > 1 ~ name[which.max(n[!name == ""])],
      TRUE ~ name[which.min(col2[!name == ""])]
    ),
    n = NULL
  )

Вывод:

# A tibble: 20 x 5
# Groups:   group [4]
   group col1    col2 name            consensus_name 
   <int> <fct>  <int> <fct>           <fct>          
 1     1 dog       40 canidae         canidae        
 2     1 dog       40 canidae         canidae        
 3     1 dog       40 canidae         canidae        
 4     1 dog       40 canidae         canidae        
 5     1 dog       40 ""              canidae        
 6     1 dog       40 canidae         canidae        
 7     1 dog       40 canidae         canidae        
 8     2 frog      85 dendrobatidae   leptodactylidae
 9     2 frog      89 leptodactylidae leptodactylidae
10     2 frog      89 leptodactylidae leptodactylidae
11     2 frog      82 leptodactylidae leptodactylidae
12     2 frog      89 ""              leptodactylidae
13     2 frog      81 ""              leptodactylidae
14     2 frog      89 dendrobatidae   leptodactylidae
15     3 horse     87 equidae1        equidae3       
16     3 donkey    76 equidae2        equidae3       
17     3 zebra     67 equidae3        equidae3       
18     4 bird      54 psittacidae     psittacidae    
19     4 bird      56 ""              psittacidae    
20     4 bird      34 ""              psittacidae    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...