【问题标题】:summarise divide two columns as percent总结将两列划分为百分比
【发布时间】:2017-11-22 18:59:22
【问题描述】:

我无法使用 Airplane Strikes 数据集找出在迁徙季节有多少加拿大鹅被杀。

#airline stats table
airlines <- sd4 %>% 
group_by(STATE) %>% 
filter(SPECIES == "Canada goose" & total_kills > 1) %>% 
mutate(fall_mig_kills = ifelse(SPECIES=="Canada goose" & INCIDENT_MONTH %in% c(9,10,11),total_kills,0)) %>% 
summarise(
pct_mig_kills = fall_mig_kills/total_kills
) %>% 
select(STATE,SPECIES,INCIDENT_MONTH,total_kills,fall_mig_kills,pct_mig_kills)`

这是我得到错误的地方: summarise( pct_mig_kills = fall_mig_kills/total_kills )

错误是:

Error in summarise_impl(.data, dots) : 
Column `pct_mig_kills` must be length 1 (a summary value), not 10

不知道在划分两个整数列时我如何得到一个长度大于 1 的值。

任何帮助将不胜感激!

本杰明

【问题讨论】:

  • 我们不知道sd4 是什么。
  • 在寻求帮助时,您应该在reproducible example 中包含示例输入数据,以便我们可以运行和测试代码。您正在使用 `group_by()`,所以看起来每个州可能有多个记录,但是当您在 summarize() 中使用 fall_mig_kills/total_kills 时,您将获得每一行的值,而不是单个汇总值。如果您希望每个状态有一个值,则需要明确说明要如何折叠值。也许sum(fall_mig_kills)/sum(total_kills)

标签: r dplyr divide summarize


【解决方案1】:

让我们阅读数据,记录所有内容,然后看看您的错误出现在哪里。

一般来说,您应该有指向原始数据集的链接或提供缩短版本以遵循reproducibility 原则。我在 Kaggle 上找到了一个 aircraft wildlife strikes, 1990-2015 数据集,我将在这里使用它。 注意:您需要有一个 Kaggle 帐户才能下载数据。也可以通过data.gov 获得。

读入数据

library(dplyr)
df <- read.csv("~/../Downloads/database.csv", stringsAsFactors = F)
> df$Species.Name[grepl("Canada goose", df$Species.Name, ignore.case = T)][1]
[1] "CANADA GOOSE"

> names(df)
 [1] "Record.ID"            "Incident.Year"        "Incident.Month"      
 [4] "Incident.Day"         "Operator.ID"          "Operator"            
 [7] "Aircraft"             "Aircraft.Type"        "Aircraft.Make"       
[10] "Aircraft.Model"       "Aircraft.Mass"        "Engine.Make"         
[13] "Engine.Model"         "Engines"              "Engine.Type"         
[16] "Engine1.Position"     "Engine2.Position"     "Engine3.Position"    
[19] "Engine4.Position"     "Airport.ID"           "Airport"             
[22] "State"                "FAA.Region"           "Warning.Issued"      
[25] "Flight.Phase"         "Visibility"           "Precipitation"       
[28] "Height"               "Speed"                "Distance"            
[31] "Species.ID"           "Species.Name"         "Species.Quantity"    
[34] "Flight.Impact"        "Fatalities"           "Injuries"            
[37] "Aircraft.Damage"      "Radome.Strike"        "Radome.Damage"       
[40] "Windshield.Strike"    "Windshield.Damage"    "Nose.Strike"         
[43] "Nose.Damage"          "Engine1.Strike"       "Engine1.Damage"      
[46] "Engine2.Strike"       "Engine2.Damage"       "Engine3.Strike"      
[49] "Engine3.Damage"       "Engine4.Strike"       "Engine4.Damage"      
[52] "Engine.Ingested"      "Propeller.Strike"     "Propeller.Damage"    
[55] "Wing.or.Rotor.Strike" "Wing.or.Rotor.Damage" "Fuselage.Strike"     
[58] "Fuselage.Damage"      "Landing.Gear.Strike"  "Landing.Gear.Damage" 
[61] "Tail.Strike"          "Tail.Damage"          "Lights.Strike"       
[64] "Lights.Damage"        "Other.Strike"         "Other.Damage"        
[67] "totalKills"

请注意,物种名称全部大写。使用grepl 而不是==,除非您确定您逐字了解该名称。

没有total_kills 变量,而Fatalities 变量代表人类 死亡人数,所以我将忽略该过滤器变量。我确实找到了Species.Quantity,这可能就是您要查找的内容,即事件中死亡的物种总数。

> unique(df$Species.Quantity)
[1] "1"        "2-10"     ""         "11-100"   "Over 100"

对于本例,我们可以将这些值转换为数字。

> dictNames <- unique(df$Species.Quantity)
> dict <- c(1, 2, 0, 11, 100)
> names(dict) <- dictNames
> dict['1']
1 
1 
> dict['2-10']
2-10 
   2 
> df <- df %>% mutate(totalKills = dict[Species.Quantity])
> table(df$totalKills, useNA = "always")

     1      2     11    100   <NA> 
146563  21852   1166     46   4477 

太好了,现在让我们看看您的代码。

试用您的代码并找出问题

> df %>% 
+   group_by(State) %>% 
+   filter(Species.Name == "CANADA GOOSE" & totalKills > 1) %>% 
+   mutate(fall_mig_kills = ifelse(Species.Name == "CANADA GOOSE" & 
+                                    Incident.Month %in% c(9,10,11),
+                                  totalKills,
+                                  0)
+          ) %>% 
+   summarise(
+     pct_mig_kills = fall_mig_kills/totalKills
+   )
Error in summarise_impl(.data, dots) : 
  Column `pct_mig_kills` must be length 1 (a summary value), not 19

嗯,让我们看看为什么会这样。通过在控制台中输入?summarise 来阅读帮助菜单:

summarise {dplyr} R 文档 将多个值减少到一个 单值

说明

summarise() 通常用于由 group_by() 创建的分组数据。 每个组的输出将有一行。

好的,所以每个组的输出将有一行由于您已经对变量进行了分组,我们需要sum总数杀死。此外,您可能希望创建一个新变量“inSeason”,它允许您适当地汇总数据。

所以,要解决您的问题,您只需添加 sum:

+   summarise(
+     pct_mig_kills = sum(fall_mig_kills)/sum(totalKills)
+   )
# A tibble: 49 x 2
   State pct_mig_kills
   <chr>         <dbl>
 1          0.70212766
 2    AK    0.50000000
 3    AL    0.00000000
 4    AR    1.00000000
 5    CA    0.06185567

无错误地重写您的代码

现在让我们将其更改为更易于阅读。你关心的是季节,而不是状态。

> df %>%
+   # inSeason = seasons we care about monitoring
+   # totalKills has NA values, we choose to put deaths at 0
+   mutate(inSeason = ifelse(Incident.Month %in% 9:11, "in", "out"),
+          totalKills = ifelse(is.na(totalKills), 0, totalKills)) %>%
+   # canadian geese only
+   filter(grepl("canada goose", Species.Name, ignore.case = T)) %>%
+   # collect data by inSeason
+   group_by(inSeason) %>%
+   # sum them up
+   summarise(totalDead = sum(totalKills)) %>%
+   # add a ratio value
+   mutate(percentDead = round(100*totalDead/sum(totalDead),0))
# A tibble: 2 x 3
  inSeason totalDead percentDead
     <chr>     <dbl>       <dbl>
1       in       838          34
2      out      1620          66

现在您可以计算出旺季与淡季、总死亡人数和百分比。如果您想添加状态,请将该变量添加到您的分组中。

另外一个注释,group_bysummarise 会自动删除其他列,因此您不需要在末尾使用 select

> df %>%
+   mutate(inSeason = ifelse(Incident.Month %in% 9:11, "in", "out"),
+          totalKills = ifelse(is.na(totalKills), 0, totalKills)) %>%
+   filter(grepl("canada goose", Species.Name, ignore.case = T)) %>%
+   group_by(State, inSeason) %>%
+   summarise(totalDead = sum(totalKills)) %>%
+   mutate(percentDead = round(100*totalDead/sum(totalDead),0))
# A tibble: 98 x 4
# Groups:   State [51]
   State inSeason totalDead percentDead
   <chr>    <chr>     <dbl>       <dbl>
 1             in        52          52
 2            out        48          48
 3    AB       in         1          50
 4    AB      out         1          50
 5    AK       in        13          33
 6    AK      out        26          67
 7    AL       in         2          40
 8    AL      out         3          60
 9    AR       in         6         100
10    CA       in        13           8

【讨论】:

  • 非常感谢您的宝贵而详尽的回答。我是堆栈溢出的新手。将来发布问题时,我一定会遵循您的所有提示。我只提供了部分代码,你是对的。我真的很感激这个帮助!因为我没有提供足够的数据,所以我标记为已回答。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多