У меня есть датафрейм услуг бронирования. Каждое бронирование имеет дату начала и окончания контракта. На определенную отчетную дату я хочу определить, активен ли контракт и, если да, то, сколько нужно выставить счет на основе ежемесячной ставки выставления счетов. Если контракт заканчивается в середине месяца, я выставляю счет на последний месяц.
Вот кадр данных:
> bookings
Account Service MonthlyRate ContractStart ContractEnd
1 A W 50 2018-01-01 2018-12-31
2 A X 75 2018-03-15 2019-03-14
3 B W 60 2018-02-28 2018-09-30
4 B X 90 2018-05-12 2019-08-11
5 B Y 45 2018-02-28 2018-09-30
6 C Y 50 2018-07-31 2019-04-30
7 D W 65 2019-01-01 2019-03-31
8 D Y 50 2018-09-01 2019-05-31
9 D Z 110 2018-08-22 2019-12-31
10 E Z 100 2018-10-01 2019-09-30
Я написал функцию, использующую lubridate для расчета ежемесячного выставления счетов.
monthly_revenue <- function(reporting_date, monthly_rate, start, end) {
contract_int <- interval(start, end) # Contract interval
# Calculate interval ending the last day of the month of contract end
end_of_month <- end
day(end_of_month) <- days_in_month(end)
end_of_month_int <- interval(start, end_of_month)
# Check if reporting date is within contract interval
if(reporting_date %within% contract_int) {
val <- 1 # bill for entire month
# If not within interval, check if contract is in its last month
} else if (reporting_date %within% end_of_month_int) {
val <- day(end) / days_in_month(end) # prorate monthly charges
} else { # Not within contract
val <- 0 # zero revenue
}
val * monthly_rate
}
Затем я устанавливаю дату выставления счета и применяю функцию по очереди к фрейму данных:
billing_date <- as.Date("2019-03-29")
revenue_for_month <-bookings %>%
rowwise() %>%
mutate(Revenue = monthly_revenue(billing_date, MonthlyRate, ContractStart, ContractEnd))
Что приводит к следующей ошибке:
Error in mutate_impl(.data, dots) :
Evaluation error: non-numeric argument to binary operator.
Я не могу сказать, связана ли проблема с моей функцией или как я выполняю итерации. Любая помощь будет с благодарностью.
[продолжение на основе полученных комментариев]
Я использую следующие вызовы библиотеки:
library(tidyverse)
library(lubridate)
А вот вывод dput для моего кадра данных:
> dput(bookings)
structure(list(Account = c("A", "A", "B", "B", "B", "C", "D",
"D", "D", "E"), Type = c("W", "X", "W", "X", "Y", "Y", "W", "Y",
"Z", "Z"), MonthlyRate = c(50L, 75L, 60L, 90L, 45L, 50L, 65L,
50L, 110L, 100L), ContractStart = structure(c(NA_real_, NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,
NA_real_), class = "Date"), ContractEnd = structure(c(NA_real_,
NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_,
NA_real_, NA_real_), class = "Date")), .Names = c("Account",
"Type", "MonthlyRate", "ContractStart", "ContractEnd"), row.names = c(NA,
-10L), spec = structure(list(cols = structure(list(Account = structure(list(), class = c("collector_character",
"collector")), Type = structure(list(), class = c("collector_character",
"collector")), MonthlyRate = structure(list(), class = c("collector_integer",
"collector")), ContractStart = structure(list(), class = c("collector_character",
"collector")), ContractEnd = structure(list(), class = c("collector_character",
"collector"))), .Names = c("Account", "Type", "MonthlyRate",
"ContractStart", "ContractEnd")), default = structure(list(), class = c("collector_guess",
"collector"))), .Names = c("cols", "default"), class = "col_spec"), class = c("tbl_df",
"tbl", "data.frame"))