Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/73.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R:在没有for循环的日期之间聚合_R_Aggregate - Fatal编程技术网

R:在没有for循环的日期之间聚合

R:在没有for循环的日期之间聚合,r,aggregate,R,Aggregate,我希望对两个日期之间有效且不使用for循环的租赁赚取的所有租金进行合计 以下是租赁数据的示例 数据帧1 StartDate EndDate MonthlyRental 2015-07-01 2015-09-30 500 2015-06-01 2015-10-31 600 2015-07-15 2016-01-31 400 2015-08-01 2015-12-31 800 我想计算每个月的租金金额,如果可能的话按比例分配(

我希望对两个日期之间有效且不使用for循环的租赁赚取的所有租金进行合计

以下是租赁数据的示例
数据帧1

StartDate     EndDate       MonthlyRental  
2015-07-01    2015-09-30    500
2015-06-01    2015-10-31    600
2015-07-15    2016-01-31    400
2015-08-01    2015-12-31    800
我想计算每个月的租金金额,如果可能的话按比例分配(如果太难的话不算NB)。例如:
数据框架2

Month        RentalIncome
2015-07-31   500+600+(400*15/31)
2015-08-31   500+600+400+800
2015-09-30   500+600+400+800
2015-10-31   600+400+800
2015-11-30   600+400+800
etc.
有人知道比简单地循环使用Dataframe2更好的方法吗

谢谢


Mike

我不确定这是否比“简单地在数据帧中循环”好——因为我确实在数据帧中循环——但这里有一种方法可以产生所需的输出

(产量与2015年7月的问题不符,因为租金将在7月支付17天,而不是15天。)

将给定的时间间隔转换为天,计算每天的租金,然后按月计算每天的租金:

library(zoo)

df1 <- data.frame(
  StartDate = as.Date(c("2015-07-01", "2015-06-01", "2015-07-15", "2015-08-01")),
  EndDate = as.Date(c("2015-09-30", "2015-10-31", "2016-01-31", "2015-12-31")),
  MonthlyRental = c(500, 600, 400, 800)
)

df1LongList <- apply(df1, MARGIN = 1, FUN = function(row) {
  return(data.frame(
    date = seq(from = as.Date(row["StartDate"]), to = as.Date(row["EndDate"]), by = "day"),
    MonthlyRental = as.numeric(row["MonthlyRental"])))
})

df1Long <- do.call("rbind", df1LongList)
df1Long$yearMon <- as.yearmon(df1Long$date)
df1Long$maxDays <- as.numeric(as.Date(df1Long$yearMon, frac = 1) - as.Date(df1Long$yearMon) + 1) # Thanks: http://stackoverflow.com/a/6244503/2706569

df1Long$rental <- df1Long$MonthlyRental / df1Long$maxDays

tapply(X = df1Long$rental, INDEX = df1Long$yearMon, FUN = sum)

# Jun 2015 Jul 2015 Aug 2015 Sep 2015 Okt 2015 Nov 2015 Dez 2015 Jan 2016 
# 600.000 1319.355 2300.000 2300.000 1800.000 1200.000 1200.000  400.000 
图书馆(动物园)

df1这里有一个可能的
data.table
解决方案(在
Hmisc
包的帮助下)。如果没有半个月的租金,这可能是一个非常简单的问题,但由于这一限制,这变得非常困难

作为补充说明,我仅假设按照您的示例,开始日期为半个月

library(data.table)
require(Hmisc)

# Converting to valid date classes
Dates <- names(df)[1:2]
setDT(df)[, (Dates) := lapply(.SD, as.Date), .SDcols = Dates]

# Handling half months
df[mday(StartDate) != 1, `:=`(GRP = seq_len(.N), 
                              mDays = mday(StartDate), 
                              StartDate = StartDate - mday(StartDate) + 1L)]

## Converting to long format
res <- df[, .(Month = seq(StartDate, EndDate, by = "month")), 
              by = .(MonthlyRental, GRP, mDays)]

## Dividing not full months by the number of days (that could be modified as per other post)
res[match(na.omit(df$GRP), GRP), MonthlyRental := MonthlyRental*mDays/monthDays(Month)]
res[, .(RentalIncome = sum(MonthlyRental)), keyby = .(year(Month), month(Month))]

#    year month RentalIncome
# 1: 2015     6          600
# 2: 2015     7         1293
# 3: 2015     8         2300
# 4: 2015     9         2300
# 5: 2015    10         1800
# 6: 2015    11         1200
# 7: 2015    12         1200
# 8: 2016     1          400
库(data.table)
要求(Hmisc)
#转换为有效日期类

日期我使用外部产品“pmin”和“pmax”来避免循环。部分覆盖的月份既困难又有趣:

library(lubridate)

df1 <- data.frame(
  StartDate = as.Date(c("2015-07-01", "2015-06-01", "2015-07-15", "2015-08-01")),
  EndDate = as.Date(c("2015-09-30", "2015-10-31", "2016-01-31", "2015-12-31")),
  MonthlyRental = c(500, 600, 400, 800)
)

d <- c( as.Date("2015-07-31"),
        as.Date("2015-08-31"),
        as.Date("2015-09-30"),
        as.Date("2015-10-31"),
        as.Date("2015-11-30"),
        as.Date("2015-12-31"),
        as.Date("2016-01-31"),
        as.Date("2016-02-29")  )

RentPerDay <- outer( df1$"MonthlyRental", days_in_month(d), "/" )

countDays <- pmin( pmax( outer( d, df1$"StartDate", "-") + 1, 0 ), days_in_month(d) ) -
             pmin( pmax( outer( d, df1$"EndDate"  , "-"), 0 ), days_in_month(d) )

rentalIncome <- colSums( t(countDays) * RentPerDay )

我稍微修改了一下我以前的回答。矩阵“RentPerDay”不是必需的。“colSums(t(countDays)*RentPerDay)”可替换为矩阵向量积。此解决方案计算的租金收入与上一个解决方案相同

library(lubridate)

ultimo_day <- function( start, end )
{
  N <- 12*(year(end) - year(start)) + month(end) - month(start) + 1
  d <- start
  day(d) <- 1
  month(d) <- month(d) + (1:N)
  return( d - as.difftime(1,units="days"))
}

countDays <- function( data, d )
{
  return( pmin( pmax( outer( d, data$"StartDate", "-") + 1, 0 ), day(d) ) -
          pmin( pmax( outer( d, data$"EndDate"  , "-"), 0 ), day(d) ) )
}

rentalIncome <- function( data,
                          d = ultimo_day( min(data$StartDate), max(data$EndDate) ) )
{
  return ( data.frame( date   = d,
                       income = ( countDays(data,d) / days_in_month(d) ) %*% data$"MonthlyRental" ) )
}

# -------- Example Data: --------

df1 <- data.frame(
  StartDate     = as.Date(c("2015-07-01", "2015-06-01", "2015-07-15", "2015-08-01", "2014-06-20")),
  EndDate       = as.Date(c("2015-09-30", "2015-10-31", "2016-01-31", "2015-12-31", "2015-07-31")),
  MonthlyRental = c(500, 600, 400, 800, 300)
)
“最后一天(开始,结束)”是“开始”和“结束”之间支付租金的天数向量:

> d <- ultimo_day( min(df1$StartDate), max(df1$EndDate))
> d
 [1] "2014-06-30" "2014-07-31" "2014-08-31" "2014-09-30" "2014-10-31" "2014-11-30" "2014-12-31" "2015-01-31" "2015-02-28" "2015-03-31" "2015-04-30"
[12] "2015-05-31" "2015-06-30" "2015-07-31" "2015-08-31" "2015-09-30" "2015-10-31" "2015-11-30" "2015-12-31" "2016-01-31"
第1行属于2014年6月,第2行属于2014年7月,…,第20行属于2016年1月

“countDays(df1,d)/days_in_month(d)”也是一个矩阵。 该矩阵的(i,j)-分量不是天数 第j个租约在第i个月有效,但该数字与 第i个月的长度:

> countDays(df1,d) / days_in_month(d)
Time differences in days
      [,1] [,2]      [,3] [,4]      [,5]
 [1,]    0    0 0.0000000    0 0.3666667
 [2,]    0    0 0.0000000    0 1.0000000
 [3,]    0    0 0.0000000    0 1.0000000
 [4,]    0    0 0.0000000    0 1.0000000
 [5,]    0    0 0.0000000    0 1.0000000
 [6,]    0    0 0.0000000    0 1.0000000
 [7,]    0    0 0.0000000    0 1.0000000
 [8,]    0    0 0.0000000    0 1.0000000
 [9,]    0    0 0.0000000    0 1.0000000
[10,]    0    0 0.0000000    0 1.0000000
[11,]    0    0 0.0000000    0 1.0000000
[12,]    0    0 0.0000000    0 1.0000000
[13,]    0    1 0.0000000    0 1.0000000
[14,]    1    1 0.5483871    0 1.0000000
[15,]    1    1 1.0000000    1 0.0000000
[16,]    1    1 1.0000000    1 0.0000000
[17,]    0    1 1.0000000    1 0.0000000
[18,]    0    0 1.0000000    1 0.0000000
[19,]    0    0 1.0000000    1 0.0000000
[20,]    0    0 1.0000000    0 0.0000000
该矩阵乘以向量“df1$MonthlyRental”,所得向量作为“收入”存储在租金收入的数据框中:

> rentalIncome(df1)
         date   income
1  2014-06-30  110.000
2  2014-07-31  300.000
3  2014-08-31  300.000
4  2014-09-30  300.000
5  2014-10-31  300.000
6  2014-11-30  300.000
7  2014-12-31  300.000
8  2015-01-31  300.000
9  2015-02-28  300.000
10 2015-03-31  300.000
11 2015-04-30  300.000
12 2015-05-31  300.000
13 2015-06-30  900.000
14 2015-07-31 1619.355
15 2015-08-31 2300.000
16 2015-09-30 2300.000
17 2015-10-31 1800.000
18 2015-11-30 1200.000
19 2015-12-31 1200.000
20 2016-01-31  400.000

您当前正在遍历Dataframe1,而不是DataFrame2(如您所写)。对的请发布您当前的代码以将Dataframe1转换为Dataframe2。我想是这样的。你看到我在代码上面的评论了吗?换句话说,我不考虑“半个月”,而是计算确切的日期。当合同在第15天开始时,你将不得不支付那一天,对吗?31-15+1=17.谢谢你的解决方案,很抱歉耽搁了这么久,我还没到办公室。这个解决方案很有效,只有一个问题:它不需要考虑几年(我意识到我的例子没有说明这一点的必要性)。目前,如果开始日期为2014年6月20日,相应的结束日期为2015年7月30日,则2015年6月和2014年6月的租金按比例计算。这有什么办法吗?谢谢,谢谢你的帮助!“RentPerDay”列对应的月份不仅是1月、2月、12月,还有2015年7月、2015年8月、2016年2月。如果有另一份租约,从2014年6月20日开始,到2015年7月31日结束,月份为2014年6月、2014年7月、2016年2月。想象一个螺旋而不是一个圆。也许在这一点上,对我的解决方案的解释是模棱两可的。在我的secomd解决方案的示例中,额外的租赁在2014年6月提供110份,在2015年6月提供300份。
> countDays(df1,d)
Time differences in days
      [,1] [,2] [,3] [,4] [,5]
 [1,]    0    0    0    0   11
 [2,]    0    0    0    0   31
 [3,]    0    0    0    0   31
 [4,]    0    0    0    0   30
 [5,]    0    0    0    0   31
 [6,]    0    0    0    0   30
 [7,]    0    0    0    0   31
 [8,]    0    0    0    0   31
 [9,]    0    0    0    0   28
[10,]    0    0    0    0   31
[11,]    0    0    0    0   30
[12,]    0    0    0    0   31
[13,]    0   30    0    0   30
[14,]   31   31   17    0   31
[15,]   31   31   31   31    0
[16,]   30   30   30   30    0
[17,]    0   31   31   31    0
[18,]    0    0   30   30    0
[19,]    0    0   31   31    0
[20,]    0    0   31    0    0
> countDays(df1,d) / days_in_month(d)
Time differences in days
      [,1] [,2]      [,3] [,4]      [,5]
 [1,]    0    0 0.0000000    0 0.3666667
 [2,]    0    0 0.0000000    0 1.0000000
 [3,]    0    0 0.0000000    0 1.0000000
 [4,]    0    0 0.0000000    0 1.0000000
 [5,]    0    0 0.0000000    0 1.0000000
 [6,]    0    0 0.0000000    0 1.0000000
 [7,]    0    0 0.0000000    0 1.0000000
 [8,]    0    0 0.0000000    0 1.0000000
 [9,]    0    0 0.0000000    0 1.0000000
[10,]    0    0 0.0000000    0 1.0000000
[11,]    0    0 0.0000000    0 1.0000000
[12,]    0    0 0.0000000    0 1.0000000
[13,]    0    1 0.0000000    0 1.0000000
[14,]    1    1 0.5483871    0 1.0000000
[15,]    1    1 1.0000000    1 0.0000000
[16,]    1    1 1.0000000    1 0.0000000
[17,]    0    1 1.0000000    1 0.0000000
[18,]    0    0 1.0000000    1 0.0000000
[19,]    0    0 1.0000000    1 0.0000000
[20,]    0    0 1.0000000    0 0.0000000
> rentalIncome(df1)
         date   income
1  2014-06-30  110.000
2  2014-07-31  300.000
3  2014-08-31  300.000
4  2014-09-30  300.000
5  2014-10-31  300.000
6  2014-11-30  300.000
7  2014-12-31  300.000
8  2015-01-31  300.000
9  2015-02-28  300.000
10 2015-03-31  300.000
11 2015-04-30  300.000
12 2015-05-31  300.000
13 2015-06-30  900.000
14 2015-07-31 1619.355
15 2015-08-31 2300.000
16 2015-09-30 2300.000
17 2015-10-31 1800.000
18 2015-11-30 1200.000
19 2015-12-31 1200.000
20 2016-01-31  400.000