Как создать таблицу частот с несколькими переменными в R, если не все значения присутствуют во всех столбцах?

#r #dataframe #apply #frequency

#r #фрейм данных #применить #частота

Вопрос:

Я хотел бы создать таблицу частот, подобную этой, в R:

 df = data.frame(aa = c(9,8,7,8), bb = c(9,7,9,8), cc = c(7,9,8,7))
apply(df, 2, table)

# outputs:  
#   aa bb cc
# 7  1  1  2
# 8  2  1  1
# 9  1  2  1
  

Но, если один из столбцов df будет иметь значение 0 (например, если мы изменим приведенное выше, чтобы df$cc не было 9 ), мы получим список вместо красивого фрейма данных.

 # example that gives a list
df = data.frame(aa = c(9,8,7,8), bb = c(9,7,9,8), cc = c(7,8,8,7))
apply(df, 2, table)
  

Какой простой способ сделать что-то подобное, что гарантирует вывод фрейма данных независимо от количества?

Я могу представить ряд решений, которые кажутся неаккуратными или взломанными, например, это дает желаемый результат:

 # example of a messy but correct solution
df = data.frame(aa = c(9,8,7,8), bb = c(9,7,9,8), cc = c(7,8,8,7))
apply(df, 2, function(x) summary(factor(x, levels = unique(unlist(df)))))
  

Есть ли более чистый способ сделать это?

Комментарии:

1. Что вы находите «беспорядочным» в найденном вами решении? Для меня выглядит нормально. Я могу придумать и другие решения, но то, являются ли они «грязными», кажется довольно основанным на мнениях. Можете ли вы привести некоторые объективные критерии?

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

Ответ №1:

Я продолжу и отвечу, хотя я все еще возражаю против отсутствия критериев. Если мы думаем о «аккуратности» как противоположности «беспорядку», то сначала нам следует привести входные данные в длинный формат. Тогда мы можем выполнить двусторонний table :

 library(tidyr)
df %>% gather %>%
  with(table(value, key))
#      key
# value aa bb cc
#     7  1  1  2
#     8  2  1  2
#     9  1  2  0
  

Спасибо Markus за базовую версию R:

 table(stack(df))
#       ind
# values aa bb cc
#      7  1  1  2
#      8  2  1  2
#      9  1  2  0
  

Комментарии:

1. В базовом table(stack(df))

2. Чувак, я думаю, что узнал о stack тебе вчера, и это уже снова пригодилось. Отличная базовая служебная функция R!

3. Технически, table(stack(df)) не возвращает фрейм данных, но as.data.frame.matrix(table(stack(df))) сделал свое дело за меня. Спасибо.

4. Таблицы не являются фреймами данных. Ни в одном из примеров в вашем вопросе или в этом ответе не приведены фреймы данных, но as.data.frame.matrix(...) вы получите фрейм данных.