2017-08-14 1 views
2

Vous souhaitez calculer une somme conditionnelle basée sur des dates spécifiées dans r. Mon échantillon df estsomme conditionnelle avec des dates dans les noms de colonne

start_date = c("7/24/2017", "7/1/2017", "7/25/2017") 
end_date = c("7/27/2017", "7/4/2017", "7/28/2017") 
`7/23/2017` = c(1,5,1) 
`7/24/2017` = c(2,0,2) 
`7/25/2017` = c(0,0,10) 
`7/26/2017` = c(2,2,2) 
`7/27/2017` = c(0,0,0) 
df = data.frame(start_date,end_date,`7/23/2017`,`7/24/2017`,`7/25/2017`,`7/26/2017`,`7/27/2017`) 

Dans Excel, il ressemble à:

enter image description here

Je veux effectuer des calculs comme indiqué dans colonne H qui est une somme conditionnelle de colonnes C à G sur la base des dates spécifiées dans colonnes A et B.

Apparemment, Excel permet colonnes à dates mais pas R.

Répondre

2

Vous pouvez y parvenir comme suit:

# number of trailing columns without numeric values 
c = 2 

# create a separate vector with the dates 
dates = as.Date(gsub("X","",tail(colnames(df),-c)),format="%m.%d.%Y") 

# convert date columns in dataframe 
df$start_date = as.Date(df$start_date,format="%m/%d/%Y") 
df$end_date = as.Date(df$end_date,format="%m/%d/%Y") 

# calculate sum 
sapply(1:nrow(df),function(x) {y = df[x,(c+1):ncol(df)][dates %in% 
    seq(df$start_date[x],df$end_date[x],by="day") ]; ifelse(length(y)>0,sum(y),0) }) 

retourne:

[1] 4 0 12 

Hope this helps!

3
#wide to long format 
    dat <- reshape(df, direction="long", varying=list(names(df)[3:7]), v.names="Value", 
      idvar=c("start_date","end_date"), timevar="Date", 
      times=seq(as.Date("2017/07/23"),as.Date("2017/07/27"), "day")) 

    #convert from factor to date class 
    dat$end_date <- as.Date(dat$end_date, format = "%m/%d/%Y") 
    dat$start_date <- as.Date(dat$start_date, format = "%m/%d/%Y") 

    library(dplyr) 
    dat %>% group_by(start_date, end_date) %>% 
      mutate(mval = ifelse(between(Date, start_date, end_date), Value, 0)) %>% 
      summarise(conditional_sum=sum(mval)) 

# # A tibble: 3 x 3 
# # Groups: start_date [?] 
# start_date end_date conditional_sum 
#  <date>  <date>   <dbl> 
# 1 2017-07-01 2017-07-04    0 
# 2 2017-07-24 2017-07-27    4 
# 3 2017-07-25 2017-07-28    12 
2

est ici une solution tout en un dplyr tuyau:

library(dplyr) 
library(lubridate) 
library(tidyr) 

df %>% 
    gather(date, value, -c(1, 2)) %>% 
    mutate(date = gsub('X', '', date)) %>% 
    mutate(date = gsub('\\.', '/', date)) %>% 
    mutate(date = mdy(date)) %>% 
    filter(date >= mdy(start_date) & date <=mdy(end_date)) %>% 
    group_by(start_date, end_date) %>% 
    summarize(Conditional_Sum = sum(value)) %>% 
    right_join(df) %>% 
    mutate(Conditional_Sum = ifelse(is.na(Conditional_Sum), 0, Conditional_Sum)) %>% 
    select(-one_of('Conditional_Sum'), one_of('Conditional_Sum')) 

## start_date end_date X7.23.2017 X7.24.2017 X7.25.2017 X7.26.2017 X7.27.2017 Conditional_Sum 
##  <fctr> <fctr>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>   <dbl> 
## 1 7/24/2017 7/27/2017   1   2   0   2   0    4 
## 2 7/1/2017 7/4/2017   5   0   0   2   0    0 
## 3 7/25/2017 7/28/2017   1   2   10   2   0    12