Создать таблицу частот уровней нескольких категориальных переменных для всех наблюдений в R - PullRequest
1 голос
/ 17 мая 2019

У меня есть набор данных, который выглядит примерно так

ID        Q1 Q2 Q3
Person1   A  C  NA
Person2   B  C  D
Person3   A  C  A

По сути, это таблица ответов на вопросы с несколькими вариантами ответов.

Я пытался найти способ, в R, создать профиль ответа для каждого человека.

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

           A    B    C   D   NA
Person1   .33   0  .33   0  .33
Person2    0   .33 .33  .33  0
Person3   .66   0  .33   0   0

Я пробовал возиться с функцией crosstab () и различными способами перемещать вещи с помощью dplyr и tidyr. Я также погуглил каждую вариацию «таблицы частот R», но не очень успешно.

Я упускаю какой-то действительно очевидный способ сделать это?

Ответы [ 3 ]

1 голос
/ 17 мая 2019

Вот способ с tidyverse -

df %>% 
  gather(var, value, -ID) %>% 
  replace_na(list(value = "Missing")) %>% 
  count(ID, value) %>% 
  group_by(ID) %>% 
  mutate(
    prop = n/sum(n)
  ) %>% 
  select(-n) %>% 
  spread(value, prop, fill = 0)

# A tibble: 3 x 6
# Groups:   ID [3]
  ID          A     B     C     D Missing
  <chr>   <dbl> <dbl> <dbl> <dbl>   <dbl>
1 Person1 0.333 0     0.333 0       0.333
2 Person2 0     0.333 0.333 0.333   0    
3 Person3 0.667 0     0.333 0       0   

Данные -

df <- read.table(text = "ID Q1 Q2 Q3
Person1 A C NA
Person2 B C D
Person3 A C A", header = T, sep = " ", stringsAsFactors = F)
0 голосов
/ 17 мая 2019

Сначала я использую melt, затем table + prop.table

s=reshape2::melt(df,id.vars='ID')
s[is.na(s)]='NA'
prop.table(table(s$ID,as.character(s$value)),1)

                  A         B         C         D        NA
  Person1 0.3333333 0.0000000 0.3333333 0.0000000 0.3333333
  Person2 0.0000000 0.3333333 0.3333333 0.3333333 0.0000000
  Person3 0.6666667 0.0000000 0.3333333 0.0000000 0.0000000
0 голосов
/ 17 мая 2019

Это похоже на Shree только с аннотацией для шагов

library(tidyverse)

df <-
  tibble(
    ID = paste0("Person", 1:3),
    Q1 = c("A", "B", "A"),
    Q2 = rep("C", 3),
    Q3 = c(NA, "D", "A")
  )

df %>% 
  # this will flip the data from wide to long
  # and create 2 new columns "var" and "letter"
  # using all the columns not = ID
  gather(key = var, value = letter, -ID) %>%
  # count how many 
  group_by(ID) %>% 
  mutate(total = n()) %>% 
  ungroup() %>% 
  # groups by ID & letter & counts, creates a column "n" 
  # can also use a group by
  count(ID, letter, total) %>% 
  # do the math
  mutate(pct = round(n/total, 2)) %>% 
  # keep just these 3 columns
  select(ID, letter, pct) %>% 
  # the inverse of gather(). Will take the letter column to
  # make new columns for each unique value and will put the 
  # pct values underneath them. Any NA will become a 0
  spread(key = letter, value = pct, fill = 0)

#  ID          A     B     C     D `<NA>`
#  <chr>   <dbl> <dbl> <dbl> <dbl>  <dbl>
# Person1  0.33  0     0.33  0      0.33
# Person2  0     0.33  0.33  0.33   0   
# Person3  0.67  0     0.33  0      0   
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...