【问题标题】:Rewrite a For Loop that Calculates Percentage Column when Total is in a Row Using Tidyverse使用 Tidyverse 重写当 Total 在一行时计算百分比列的 For 循环
【发布时间】:2018-01-25 08:16:16
【问题描述】:
library(tidyverse)

我想使用 dplyr、tidyr 和 purrr 以 Tidyverse 语法重写下面的 for 循环代码。

for (i in seq_along(Data3)) {
Data3[[i]]$Count <- as.numeric(Data3[[i]]$Count)
n <- nrow(Data3[[i]])
Data3[[i]]$perc <- Data3[[i]]$Count / Data3[[i]]$Count[n]
} 

下面的示例数据:

Loc<-c("Montreal","Toronto","Vancouver","Quebec","Ottawa","Hamilton","Total")
Count<-c("2344","2322","122","45","4544","44","9421")

Data<-data_frame(Loc,Count)
Data2<-data_frame(Loc,Count)
Data3<-list(Data,Data2)

这就是我想要实现的目标:

每个数据框的“Loc”列中都有“Total”以及“Count”列的相应总和。我想通过将“计数”列中的每个值除以总数来计算每个数据帧的百分比,总数是“计数”列中的最后一个数字。

我希望将百分比添加为每个数据框的新列。 对于此示例,总计是列中的最后一个数字,但实际上,它可能混合在列中的任何位置,并且可以通过“Loc”列中相应的“Total”值找到。

我一直在使用 purrr::map,但我不确定如何计算百分比。

Data3%>%map(~mutate(.x,paste0(round(100*  (MISSING PERCENTAGE),2),"%"))  

【问题讨论】:

  • 本网站不适用于“编写我的代码”问题。您已经尝试了哪些方法,哪些方法没有奏效,或者您遇到了哪些问题?
  • 我添加了一个我想到的代码示例,但我真的坚持百分比计算。我尝试寻找有关此的其他帖子,但找不到任何内容。

标签: r tidyverse


【解决方案1】:

我将使用基础 R:

首先确保您的数据具有 Loc 作为字符而不是因子:

 Loc<-c("Montreal","Toronto","Vancouver","Quebec","Ottawa","Hamilton","Total")
 Count<-c(2344,2322,122,45,4544,44,9421)

 Data<-data.frame(Loc,Count,stringsAsFactors = F)

 Data3<-list(Data,Data)

 lapply(Data3,function(x) {x[,"Percentage"]=100*x[,2]/x[x[,1]=="Total",2];x})


 [[1]]
         Loc Count  Percentage
 1  Montreal  2344  24.8805859
 2   Toronto  2322  24.6470651
 3 Vancouver   122   1.2949793
 4    Quebec    45   0.4776563
 5    Ottawa  4544  48.2326717
 6  Hamilton    44   0.4670417
 7     Total  9421 100.0000000

 [[2]]
         Loc Count  Percentage
 1  Montreal  2344  24.8805859
 2   Toronto  2322  24.6470651
 3 Vancouver   122   1.2949793
 4    Quebec    45   0.4776563
 5    Ottawa  4544  48.2326717
 6  Hamilton    44   0.4670417
 7     Total  9421 100.0000000

如果您的目标是确实使用mappurr 中的map 和 Base R 中的Map 之间没有太大区别。那么我可以给出如下提示,它会给出与上面相同的解决方案,逻辑几乎相似:

Data3%>%map(~mutate(.x,'%'=100*Count/Count[Loc=="Total"]))

我使用了 % 符号。我可以写百分比...

希望这会有所帮助

【讨论】:

    【解决方案2】:

    如果您想保留“总计”行,这将执行您的任务。但是,在单个列中混合不同类型的值对于您的数据来说是一种非常不整洁的形式。风险自负。

    Data %>% 
      mutate(Count_type = ifelse(Loc == "Total", "Total", "Component") %>% 
      group_by(Count_type) %>%
      mutate(Count_pct = Count/sum(Count))
    

    更好的解决方案是简单地去掉“总计”行,因为它们可以在您需要时轻松计算为额外的列。

    Data %>% 
      filter(Loc != "Total") %>%
      mutate(Count_pct = Count/sum(Count))
    

    Data3 而言,您将数据帧存储在列表中是否有原因?你说得对,purrr 可以解决这个问题,但还有更简单的方法:

    Data3 <- bind_rows("Data" = Data, "Data2" = Data2, .id = "Source") %>% group_by(Source)
    

    然后只需将Data3 替换为上述任一管道的开始即可。

    如果您使用列表是因为您的数据出于某种原因以列表形式提供给您,那么您的 map 代码接近正确。您应该能够弄清楚如何使用这些 sn-ps 处理数据帧列表。

    【讨论】:

      猜你喜欢
      • 2022-07-06
      • 2020-12-22
      • 2015-03-15
      • 1970-01-01
      • 1970-01-01
      • 2021-04-23
      • 2022-06-23
      • 2020-12-25
      • 1970-01-01
      相关资源
      最近更新 更多