Как применить комбинированные критерии фильтра в функции для проведения простого частотного анализа - PullRequest
0 голосов
/ 25 апреля 2020

Вот некоторые данные, демонстрирующие мою проблему:

garden <- c(1,2,3,4,5,6,7,8,9,10) %>% as.numeric
apples <- c(1,0,0,0,1,0,0,NA,NA,1) %>% as.integer ()
cherries <- c(0,1,0,0,1,1,1,NA,NA,1) %>% as.integer ()
pears <- c(0,NA,1,0,0,1,1,1,0,0)  %>% as.integer ()
veg_tomatoes <- c(0,0,0,0,1,0,0,1,0,NA) %>% as.integer ()
veg_onions <- c(0,0,0,0,0,1,1,0,0,0) %>% as.integer ()
veg_peas <- c(0,0,0,0,0,0,0,0,0,1) %>%  as.integer ()
veg_beans <- c(0,0,0,0,0,0,0,1,0,1) %>% as.integer ()

garden <- data.frame(garden,apples,cherries,pears,veg_tomatoes,veg_onions,veg_peas,veg_beans)

Я хотел бы сделать следующее:
a) Подсчитать количество и процент садов только с одним растением (например, число садов только с яблонями, только вишни и т. д. c)
b) Подсчитайте количество и процент садов с фруктовыми деревьями и помидорами
c) Подсчитайте количество и процент садов с любым фруктовое дерево и один или несколько овощей, кроме помидоров

Я ищу функциональное решение этой проблемы. Моя идея состояла в том, чтобы начать с отдельного lists для фруктов, овощей и списка, включающего все фрукты и овощи, и работать оттуда. Однако я испытываю трудности, когда пытаюсь объединить различные критерии filter в анонимном вызове функции, используя lapply. Для одного столбца я мог бы написать что-то вроде filter (garden, apples == 1, cherries == 0, pears == 0, veg_tomatoes == 0, veg_onions == 0, veg_peas == 0, veg_beans == 0) %>% nrow () для абсолютных чисел. Но даже для одного столбца это решение не выглядит хорошим, не говоря уже о необходимости повторять это снова и снова. Может быть, у кого-то из вас есть решение, как подходить к такого рода задачам и структурировать функциональные аргументы для получения желаемых частотных результатов.

Ответы [ 2 ]

1 голос
/ 25 апреля 2020

Проблемы такого рода можно решать с помощью функций, в которых гранулярность вопросов позволяет вам получить несколько запросов и, следовательно, несколько ответов.

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

Я включил сценарий, основанный на подходе «Tidyverse», я не гарантирую, не уверен, что он наиболее эффективен. Но принципы могут быть применены к каждому из ваших вопросов.

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

Я извините за то, что по своему опыту я не нашел простого способа сделать это.


library(dplyr)
library(tidyr)
library(stringr)

garden <- c(1,2,3,4,5,6,7,8,9,10) %>% as.numeric
apples <- c(1,0,0,0,1,0,0,NA,NA,1) %>% as.integer ()
cherries <- c(0,1,0,0,1,1,1,NA,NA,1) %>% as.integer ()
pears <- c(0,NA,1,0,0,1,1,1,0,0)  %>% as.integer ()
veg_tomatoes <- c(0,0,0,0,1,0,0,1,0,NA) %>% as.integer ()
veg_onions <- c(0,0,0,0,0,1,1,0,0,0) %>% as.integer ()
veg_peas <- c(0,0,0,0,0,0,0,0,0,1) %>%  as.integer ()
veg_beans <- c(0,0,0,0,0,0,0,1,0,1) %>% as.integer ()

garden <- data.frame(garden,apples,cherries,pears,veg_tomatoes,veg_onions,veg_peas,veg_beans)

g <- 
  garden %>% 
  pivot_longer(cols = apples:veg_beans, names_to = "plant", values_to = "pres") %>% 
  mutate(type = case_when(str_detect(plant, "veg") ~ "veg",
                          TRUE ~ "tree"),
         plant = str_remove(plant, "veg_"))

# Now you can carry out all the analysis you want

# a) Count the number and percentage of gardens with one sort of fruit tree or one sort of vegetable only (no other fruits, no other vegetables)

q_a <- 
  g %>% 
  group_by(garden, type) %>% 
  summarise(sum_type = sum(pres, na.rm = TRUE)) %>% 
  pivot_wider(names_from = type, values_from = sum_type) %>% 
  mutate(type_nr = sum(tree, veg)) %>% 
  filter(type_nr == 1) %>% 
  ungroup() %>% 
  summarise(count = n())

q_a

# This gives you the number of gardens which meet your criteria

total_gardens  <- 10

q_a_pc <- paste0(q_a * 100 / total_gardens, "%")

q_a_pc

0 голосов
/ 25 апреля 2020

Вот мое решение, использующее несколько критериев фильтрации в lapply, как изначально и требовалось. Решение состояло в том, чтобы вызвать нужный столбец в каждом filter, используя [[x]], и объединить его с другим «итоговым» столбцом, содержащим требуемый критерий.

library (tidyverse)

fruits <- data.frame(garden,apples,cherries,pears)
vegs <- data.frame(garden,veg_tomatoes,veg_onions,veg_peas,veg_beans)
total <- data.frame(garden,apples,cherries,pears,veg_tomatoes,veg_onions,veg_peas,veg_beans)

fruitlist <- list("apples", "cherries", "pears")


# a) Number of gardens with one sort of plant only
plantlist <- list("apples", "cherries", "pears", "veg_tomatoes","veg_onions","veg_peas","veg_beans")
total$plants <- rowSums(total[,2:8], na.rm = TRUE)

# Select gardens with only one plant
oneplant_freq <- lapply (plantlist, function (x){
  one_plant <- total %>% filter (total[[x]] == 1 & plants == 1) %>% 
    nrow ()
})

names(oneplant_freq) <- plantlist
oneplant_freq
# b) Either sort of fruit tree & tomatoes 
vegs$other_than_tom <- rowSums(vegs[,3:5], na.rm = FALSE) # new column showing the number of vegetables other than tomatoes

# Join for fruit trees & tomatoes
tom_freq <- lapply (fruitlist, function (x){
  fruits_n_tom <- inner_join(vegs, fruits, by = "garden") %>%
    filter (veg_tomatoes == 1 & other_than_tom == 0 & fruits[[x]] == 1) %>% 
    nrow ()
})

names(tom_freq) <- fruitlist
tom_freq
# c) Either sort of fruit tree & vegetables other than tomatoes

# Join for fruit trees and other vegetables than tomatoes
other_freq <- lapply (fruitlist, function (x){
  fruits_n_others <- inner_join(vegs, fruits, by = "garden") %>%
    filter (veg_tomatoes == 0 & other_than_tom >=1 & fruits[[x]] == 1) %>% 
    nrow ()
})

names(other_freq) <- fruitlist

other_freq

Теперь, когда абсолютные числа доступны из lists, расчетные проценты больше не являются проблемой.

...