【问题标题】:How to apply combined filter criteria in a function to conduct a simple frequency analysis如何在函数中应用组合过滤条件来进行简单的频率分析
【发布时间】:2020-08-08 13:27:40
【问题描述】:

这里有一些数据来证明我的问题:

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) 计算只有一种植物的花园的数量和百分比(例如,只有苹果树、只有樱桃树等的花园数量)
b) 计算种植果树和西红柿的花园的数量和百分比
c) 计算种植果树和一种或多种除西红柿以外的蔬菜的花园的数量和百分比

我正在寻找这个问题的实用解决方案。我的想法是从单独的lists 开始,用于水果、蔬菜和包括所有水果和蔬菜的列表,然后从那里开始工作。但是,当我尝试使用lapply 在匿名函数调用中组合各种filter 标准时,我感到很困难。对于单个列,我可以为绝对数字写类似 filter (garden, apples == 1, cherries == 0, pears == 0, veg_tomatoes == 0, veg_onions == 0, veg_peas == 0, veg_beans == 0) %&gt;% nrow () 的内容。但即使对于一个专栏,这个解决方案看起来也不是很好,更不用说不得不一遍又一遍地重复这个问题。也许你们中的某个人有一个解决方案,可以解决如何处理这类任务并构造函数参数以获得所需的频率结果。

【问题讨论】:

  • 您需要将数据转换为长格式,以便您的数据框具有以下列标题:花园、类型 = 蔬菜或树、植物 = 苹果、樱桃等,最后是一个布尔值,表示如果植物是否存在。

标签: r functional-programming iteration


【解决方案1】:

这是我最初需要的在lapply 中使用多个过滤条件的解决方案。解决方案是使用[[x]] 在每个filter 中调用所需的列,并将其与另一个包含所需标准的“摘要”列组合。

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 获得绝对数字,计算百分比不再是问题。

【讨论】:

    【解决方案2】:

    这类问题可以通过问题的粒度允许您最终得到多个查询并因此得到多个答案的函数来处理。

    但是,似乎总是有这样的情况,最终不得不编写多个小查询来获得所需的答案。

    我已经包含了一个基于 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
    
    

    【讨论】:

    • @Peter 感谢您在这么短的时间内为我的问题提出解决方案!将来我肯定会更频繁地使用长格式。暂时我想使用我在下面提出的解决方案坚持宽格式。我还编辑了我的问题,因为 a) 基本上应该计算只有一种植物的花园。对不起,误导性的措辞。
    猜你喜欢
    • 2016-03-01
    • 2011-12-30
    • 2021-11-25
    • 2017-04-03
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 2022-08-08
    • 1970-01-01
    相关资源
    最近更新 更多