【问题标题】:R - Count observations (strings) in a column and calculate as a percentage of overall observationsR - 计算列中的观测值(字符串)并计算为总体观测值的百分比
【发布时间】:2021-09-17 18:55:18
【问题描述】:

嗨,有一些看起来像这样的数据:

ID   Item     Class  Value  Date
1    Eggs     A      5      07/07/21
2    Eggs     A      4.5    07/07/21
3    Cereal   C      2      07/07/21
4    Eggs     B      3.5    07/07/21
5    Bread    B      2.5    07/07/21
6    Juice    A      3      07/07/21
7    Juice    C      1.5    07/07/21
8    Eggs     C      2      07/07/21
9    Bread    A      3      07/07/21
10   Juice    A      3      07/07/21

这只是一个示例,实际数据大约有 8k 行(并且有 300 多个数据帧)。我想创建一个新的 df

  1. 计算Item列中观察值的百分比(例如列中有10个项目,其中Eggs有4个,因此Eggs的百分比为40)
  2. 计算每个Item 组的平均Value

理想情况下,最终数据应如下所示:

Item    Percentage  Average_Value  Date
Eggs    40          3.75           07/07/21
Cereal  10          2              07/07/21
Bread   20          2.75           07/07/21
Juice   30          2.5            07/07/21

有几点需要注意 - 我想对 300 多个不同的 csv(我的数据存储在其中)执行此操作,并使用这些新信息创建一个 df。每个 csv 引用不同的日期,因此最终的 df 看起来像上面的样子,只有另外四行,但具有不同的值和不同的日期。我知道我需要为此使用 for 循环,也许我应该稍后弄清楚那部分,但我认为现在值得一提。最后,在某个时候,我可能还想计算Class 的平均值。我会更好地为此制作一个单独的 df,因为我看不出我还能如何做到这一点?

【问题讨论】:

    标签: r count percentage


    【解决方案1】:

    您可以使用aggregateaggregateValue ~ Item 的结果形式proportionsproportionsproportions 的结果Value ~ Item。如果Date 也需要在那里,可以使用cbinddata.frame 添加。

    merge(aggregate(cbind(Average_Value = Value) ~ Item, x, mean)
        , proportions(table(x$Item))*100
        , by.y=1, by.x="Item")[c(1,3,2)]
    #    Item Freq Average_Value
    #1  Bread   20          2.75
    #2 Cereal   10          2.00
    #3   Eggs   40          3.75
    #4  Juice   30          2.50
    

    或者只使用aggregate:

    aggregate(Value ~ Item, x, function(y) c(Freq=length(y)/nrow(x)*100, Average=mean(y)))
    #    Item Value.Freq Value.Average
    #1  Bread      20.00          2.75
    #2 Cereal      10.00          2.00
    #3   Eggs      40.00          3.75
    #4  Juice      30.00          2.50
    

    【讨论】:

    • 您好,谢谢您的建议。我最终使用了 dplyr / summarise / group_by 方法(主要是因为它有点短),但我相信这也有效:)
    【解决方案2】:

    这行得通吗:

    library(dplyr)
    df %>% group_by(Item) %>% summarise(Percentage = n()/nrow(df)*100, Average_Value = mean(Value))
    # A tibble: 4 x 3
      Item   Percentage Average_Value
      <chr>       <dbl>         <dbl>
    1 Bread          20          2.75
    2 Cereal         10          2   
    3 Eggs           40          3.75
    4 Juice          30          2.5 
    

    【讨论】:

    • 这很好用,谢谢!我唯一需要做的就是添加日期列。关于如何做到这一点的任何想法?我敢肯定这可能很简单,但编程不是我的强项!
    • @Japes,如果您还需要Date 列,请尝试:df %&gt;% group_by(Item, Date) %&gt;% summarise(Percentage = n()/nrow(df)*100, Average_Value = mean(Value))
    • 太棒了,就像魅力一样,谢谢!如果我可以大胆地再问一件事......如果我还想计算另一列的平均值,我们称之为value2(同样,它将按Item分组),我将如何添加那到这行代码?基本上,我可以在一行代码中计算两列的平均值吗?
    • 误报,经过反复试验才发现。在此处发布以防对其他人有用:df %&gt;% group_by(Item, Date) %&gt;% summarise(Percentage = n()/nrow(df)*100, Average_Value = mean(Value),Average_Value2 = mean(Value2))
    【解决方案3】:

    使用list.files 列出您要使用的所有文件。使用map_df 将它们合并到一个文件中,并为每个Date 计算Item 存在的百分比及其平均值。

    library(tidyverse)
    
    filenames <- list.files(pattern = '\\.csv$')
    
    map_df(filenames, read_csv) %>%
      group_by(Date, Item) %>%
      summarise(Percentage = n(), 
                Average_Value = mean(Value)) %>%
      mutate(Percentage = prop.table(Percentage) * 100) %>%
      ungroup -> result
    
    result
    

    【讨论】:

      【解决方案4】:

      tidyverse中执行这些步骤

      • 将工作目录设置为存储 300 多个 csv 文件的目录
      • 将所有 300 多个 csv 名称读入temp
      • 假设每个 csv 名称都指向您的 date,否则您必须稍微调整一下代码
      • 使用mapimap_dfr 如下所述,您可以为每个文件只执行一次相同的代码,因此您将拥有一个数据帧
      setwd('my/path/here')
      
      temp <- list.files(pattern = '*.csv')
      
      library(tidyverse)
      
      map(temp, read.csv) %>% setNames(gsub('.csv', '', temp)) %>%
        imap_dfr(~ .x %>% group_by(item) %>%
               summarise(Percentage = n()/nrow(df)*100, 
                         Average_Value = mean(Value), .groups = 'drop') %>%
               mutate(Date = .y))
      

      如果您的所有 csv 文件都包含日期列,请执行此操作

      map_dfr(temp, ~read.csv(.x) %>% group_by(item, date) %>%
                summarise(Percentage = n()/nrow(df)*100, 
                          Average_Value = mean(Value), .groups = 'drop'))
      

      【讨论】:

      • 非常感谢@AnilGoyal。完美运行。您知道如何添加包含项目数(以及百分比)的列吗?
      • @Japes,是的!你能告诉我几行你的文件是怎样的吗?以及它是如何命名的?
      • 最好在私聊中继续这个?我这里的字符有限,无法写出示例数据! :)
      • @Japes,你可以给我发邮件
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-04-19
      • 1970-01-01
      • 2020-12-05
      • 1970-01-01
      • 2016-02-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多