如何以编程方式选择要突变的列?

时间:2019-06-10 17:53:49

标签: r dplyr mutate

示例数据:

Project  2016   2017   2018   2019
Proj1      42     36    400    250
Proj2      96    780     60    900
Proj3     180    230      0      0

我有今年的一组财务数据,以及前几年的财务数据。我正在尝试对数据进行突变,以便将前三年添加到“以前的资金”列中。

数据中的列标记为2016、2017、2018、2019 ...等

Totals<-Totals %>% mutate("Previous Years"=`2016`+`2017`+`2018`)

现在,我实际上正在尝试进行设置,以便可以通过编程方式进行选择。明年,我自然希望查看2017年,2018年和2019年的数据,我希望对其进行设置,以便我可以输入年份数字,然后它将使用代码选择正确的列。

year = 2019

index<-which(colnames(Totals)==year)

Totals<-Totals%>%
##Here's where it gets hairy
mutate("Previous Years"=Totals[index-3]+Totals[index-2]+Totals[index-1])

Error: Column `Previous Years` is of unsupported class data.frame

因此,存在一些问题。显然,我打错了电话,上面的方案1就像一个超级按钮,第二个方案给出了一个错误。我觉得这与通常用于调用dplyr中具有不同名称的列的倒钩有关。

做这样的事情的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

我认为您的数据不整洁。如果使它整洁,事情就会变得容易。例如:

读入数据

library(dplyr)
library(tidyr)

Totals <- data.table::fread('Project  2016   2017   2018   2019
Proj1     $42    $36   $400   $250
Proj2     $96   $780    $60   $900
Proj3    $180   $230     $0     $0', header = TRUE)

year <- 2019

整理并计算以前的资金。

summ <- Totals %>% 
  gather(Year, Funding, -Project) %>% 
  mutate(Funding = readr::parse_number(Funding)) %>% 
  group_by(Project) %>% 
  summarise(Previous_funding = sum(Funding[Year %in% (year - 3):(year - 1)]))
# A tibble: 3 x 2
  Project Previous_funding
  <chr>              <dbl>
1 Proj1                478
2 Proj2                936
3 Proj3                410

您还可以使用mutate代替summarise来保留所有数据:

# A tibble: 12 x 4
# Groups:   Project [3]
   Project Year  Funding Previous_funding
   <chr>   <chr>   <dbl>            <dbl>
 1 Proj1   2016       42              478
 2 Proj2   2016       96              936
 3 Proj3   2016      180              410
 4 Proj1   2017       36              478
 5 Proj2   2017      780              936
 6 Proj3   2017      230              410
 7 Proj1   2018      400              478
 8 Proj2   2018       60              936
 9 Proj3   2018        0              410
10 Proj1   2019      250              478
11 Proj2   2019      900              936
12 Proj3   2019        0              410

或者,如果需要,您可以将以前的资金重新添加到原始的宽表中:

left_join(Totals, summ, 'Project')
 Project 2016 2017 2018 2019 Previous_funding
1   Proj1  $42  $36 $400 $250              478
2   Proj2  $96 $780  $60 $900              936
3   Proj3 $180 $230   $0   $0              410

答案 1 :(得分:0)

使用示例数据,

library(tidyverse)

adf <- tibble(
  project = c("pro1","pro2","pro3"),
  `2016` = c(42,96,180),
  `2017` = c(36,780,230),
  `2018` = c(400,60,0),
  `2019` = c(250,900,0)
)

现在让我们编写一个函数,将指定年份的总和相加

previous <- function(data, year){
  data%>%gather(Year, Funding, -project)%>%
    mutate_at(vars(Year), list(~as.numeric(.)))%>%
    split(.$project)%>%
    map(~(.)%>%filter(Year < 
    year)%>%summarise(UQ(paste0("Prior_to_",as.character(year))) := 
    sum(Funding)))%>%bind_rows()%>%
    bind_cols(data,.)
}

现在让我们添加一个新列,其中包含2018年之前几年的资金总和。

> previous(data = adf, year = 2018)
# A tibble: 3 x 6
  project `2016` `2017` `2018` `2019` Prior_to_2018
  <chr>    <dbl>  <dbl>  <dbl>  <dbl>         <dbl>
1 pro1        42     36    400    250            78
2 pro2        96    780     60    900           876
3 pro3       180    230      0      0           410
>

您还可以在函数中使用group_by(),如下所示:

previous <- function(data, year){
  data%>%gather(Year, value, -project)%>%
    mutate_at(vars(Year), list(~parse_number(.)))%>%
    group_by(project)%>%
    summarise(UQ(paste0("Prior_to_",as.character(year))) := 
sum(value[Year < year]))%>%
    left_join(data, ., by = 'project')
}