R 将特定函数应用于数据帧的所有行时出错
如果这个问题以前已经解决过,我会提前道歉,但是我已经试着把所有与ddply、sapply和apply相关的问题都找遍了,我一辈子都想不出这个问题 我已经编写了一个函数countMonths,它以计费周期中的天、月和总天数作为参数,并返回计费周期所属的日历月数:R 将特定函数应用于数据帧的所有行时出错,r,dataframe,plyr,R,Dataframe,Plyr,如果这个问题以前已经解决过,我会提前道歉,但是我已经试着把所有与ddply、sapply和apply相关的问题都找遍了,我一辈子都想不出这个问题 我已经编写了一个函数countMonths,它以计费周期中的天、月和总天数作为参数,并返回计费周期所属的日历月数: countMonths <- function(day, month, cycle.days) { month.days <- c(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 3
countMonths <- function(day, month, cycle.days) {
month.days <- c(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
if (month < 1 | month > 12 | floor(month) != month) {
cat("Invalid month value, must be an integer from 1 to 12")
} else if (day < 1 | day > month.days[month]) {
cat("Invalid day value, must be between 1 and month.days[month]")
} else if (cycle.days < 0) {
cat("Invalid cycle.days value, must be >= 0")
} else {
nmonths <- 1
day.ct <- cycle.days - day
while (day.ct > 0) {
nmonths <- nmonths + 1
month <- ifelse(month == 1, 12, month - 1) # sets to previous month
day.ct <- day.ct - month.days[month] # subtracts days of previous month
}
nmonths
}
}
我尝试了几种选择,但没有一种效果好。具体来说,我需要能够将给定变量的值作为标量(或长度为1的向量)传递给数据帧中的每一行,但它们总是作为向量传递:
> cons2$tot.months <- countMonths(cons2$day, cons2$month, cons2$cycle.days)
Warning messages:
1: In if (month < 1 | month > 12 | floor(month) != month) { :
the condition has length > 1 and only the first element will be used
2: In if (day < 1 | day > month.days[month]) { :
the condition has length > 1 and only the first element will be used
3: In if (cycle.days < 0) { :
the condition has length > 1 and only the first element will be used
4: In while (day.ct > 0) { :
the condition has length > 1 and only the first element will be used
5: In while (day.ct > 0) { :
the condition has length > 1 and only the first element will be used
>总消费2美元12个月|楼层(月)!=月份{:
条件的长度大于1,并且只使用第一个元素
2:如果(天<1 |天>月。天[月]{:
条件的长度大于1,并且只使用第一个元素
3:在if(cycle.days<0)中{:
条件的长度大于1,并且只使用第一个元素
4:while(day.ct>0){:
条件的长度大于1,并且只使用第一个元素
5:while(day.ct>0){:
条件的长度大于1,并且只使用第一个元素
我最终能够使用ddply获得正确的结果,将每一行视为自己的组,但这需要很长时间:
cons2 <- ddply(cons2, .(account, year, month, day), transform,
tot.months = countMonths(day, month, cycle.days)
)
cons2要使函数工作,可以使用mapply
将函数依次应用于传递给它的所有向量的每个元素。因此,您可以执行以下操作:
mapply(countMonths,cons2$day,cons2$month,cons2$cycle.days)
正如我在评论中提到的那样,有更简单的方法可以做到这一点。例如,我认为这会奏效:
cons2$read.date=as.Date(cons2$read.date)
monnb <- function(d){ lt <- as.POSIXlt(as.Date(d, origin="1900-01-01")); lt$year*12 + lt$mon }
mondf <- function(d1, d2) monnb(d2) - monnb(d1)
mondf(cons2$read.date-cons2$cycle.days,cons2$read.date) + 1
至于对函数的注释,我认为它是有效的,但它没有利用R中的向量运算。我从另一个答案中得到的函数非常灵活,因为它允许您一次向它提供一个完整的日期向量,而不是依次循环每个向量。如果您使用dput,将非常方便(负责人(委员会2[-1],10))
,所以我们可以直接剪切并粘贴到会话中。@nograps:done。谢谢你的建议。另外,它没有回答你的具体问题,但它解决了计算日期之间日历月数的问题。我不确定将其标记为重复是否有帮助?我的问题不在于该函数本身-它似乎在工作或者单个输入值。但是,我在将其应用于数据的每一行时遇到了问题。我包含了该函数,因此可以清楚地知道函数返回的内容,以防这影响到我的应用问题。当然,可以使用xts包中的nmonths
之类的东西来获得更简单的解决方案……这很有效,谢谢!感谢我的支持通过自己的学习,你能描述一下你所看到的功能问题吗?
cons2$read.date=as.Date(cons2$read.date)
monnb <- function(d){ lt <- as.POSIXlt(as.Date(d, origin="1900-01-01")); lt$year*12 + lt$mon }
mondf <- function(d1, d2) monnb(d2) - monnb(d1)
mondf(cons2$read.date-cons2$cycle.days,cons2$read.date) + 1
countMonths <- function(day, month, cycle.days) {
month.days <- c(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
stopifnot(month >=1 & month <= 12 & floor(month)==month & cycle.days >=0 & day >= 1 & day <= month.days[month])
nmonths <- 1
day.ct <- cycle.days - day
while (day.ct > 0) {
nmonths <- nmonths + 1
month <- ifelse(month == 1, 12, month - 1) # sets to previous month
day.ct <- day.ct - month.days[month] # subtracts days of previous month
}
nmonths
}