Как подсчитать частоту строк на основе значений в 3 столбцах в Rstudio

#r

#r

Вопрос:

У меня есть тысячи строк данных, которые выглядят следующим образом

 df <- data.frame(
thing_code = c("X123", "X123", "Y123", "Y123", "Y123", "Y123", "Z123", "Z123", "Z123", "Z123", "A456", "A456", "A456", "A456", "A456"),
year = c("2001", "2001", "2004", "2004", "2004", "2004", "2004", "2004", "2004", "2004", "2007", "2007", "2007", "2007", "2007"),
country = c("Vietnam", "Vietnam", "US", "US", "Singapore", "Vietnam", "Japan", "Vietnam", "Vietnam", "Cambodia", "Vietnam", "Vietnam", "Iran", "China", "Germany"))
  

при этом я хочу подсчитать долю вклада стран для каждой вещи (представленной thing_code) в год. Категории, которые я хочу для подсчета, следующие:

  • Вьетнам (локальная страна в этом примере)
  • SEAsian (все другие страны Юго-Восточной Азии, кроме Вьетнама)
  • Нелокальный (другие страны, кроме Вьетнама и Приморья)

Я хочу иметь возможность придумать что-то вроде этого:

 # thing_codeyear    location    freq    percentage
# X123      2001    Vietnam     2       1
# Y123      2004    Vietnam     1       0.25
# Y123      2004    Non-local   2       0.5 
# Y123      2004    SEAsian     1       0.25
# Z123      2004    Non-local   1       0.25
# Z123      2004    Vietnam     2       0.5
# Z123      2004    SEAsian     1       0.25
# A456      2007    Vietnam     2       0.4
# A456      2007    Non-local   3       0.6
  

freq будет как счетчик для вышеупомянутых категорий, а percentage будет просто процентом вклада каждой категории.

Пока что мой код выглядит следующим образом

 Vietnam <- df %>% filter(str_detect(country, "Vietnam"))

thing_code_year <- subset(Vietnam, select=c(thing_code, year))
freq <- table(thing_code_year)

frequency <- as.data.frame(freq)
frequency <- frequency %>% filter(Freq!=0)
  

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

Ответ №1:

Это должно дать желаемый результат. Вы можете использовать case_when для создания новой переменной, которая задает location , используя логику, которую вы описали выше. Далее вы group_by вводите код, год и вновь созданные location данные, чтобы рассчитать частоту каждой категории в location (вьетнамская, морская, нелокальная). Затем вы можете group_by по коду и году рассчитать процентное соотношение категорий в location .

 library(dplyr)

df <- data.frame(
  thing_code = c("X123", "X123", "Y123", "Y123", "Y123", "Y123", "Z123", "Z123", "Z123", "Z123", "A456", "A456", "A456", "A456", "A456"),
  year = c("2001", "2001", "2004", "2004", "2004", "2004", "2004", "2004", "2004", "2004", "2007", "2007", "2007", "2007", "2007"),
  country = c("Vietnam", "Vietnam", "US", "US", "Singapore", "Vietnam", "Japan", "Vietnam", "Vietnam", "Cambodia", "Vietnam", "Vietnam", "Iran", "China", "Germany"))

SEAsian <- c("Vietnam", "Singapore", "Cambodia")

df %>% 
  mutate(location = case_when(
    country == "Vietnam" ~ "Vietnam",
    country %in% SEAsian[SEAsian != "Vietnam"] ~ "SEAsian",
    !country %in% SEAsian ~ "Non-local"
  )) %>% 
  group_by(thing_code, year, location) %>% 
  summarise(freq = n()) %>% 
  group_by(thing_code, year) %>% 
  mutate(percentage = freq/sum(freq))
  

Вывод:

   thing_code year  location   freq percentage
  <fct>      <fct> <chr>     <int>      <dbl>
1 A456       2007  Non-local     3       0.6 
2 A456       2007  Vietnam       2       0.4 
3 X123       2001  Vietnam       2       1   
4 Y123       2004  Non-local     2       0.5 
5 Y123       2004  SEAsian       1       0.25
6 Y123       2004  Vietnam       1       0.25
7 Z123       2004  Non-local     1       0.25
8 Z123       2004  SEAsian       1       0.25
9 Z123       2004  Vietnam       2       0.5 
  

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

1. Я получаю эту ошибку Error: n() should only be called in a data context ? Я думаю, это из-за summarise(freq = n())

2. Мой плохой. Функция summarise также присутствует в пакете «plyr». Решается с помощью dplyr::summarise(freq = n()).