我如何应用按行操作时可以“看到”前面结果的函数?
这经常发生,但是我当前的问题要求学生的运行总计,如果总计未达到5,则会重置。
示例数据:
> df
row Student Absent Consecutive.Absences
1 A 0 0
2 A 1 1
3 A 1 2
4 A 0 0 <- resets to zero if under 5
5 A 0 0
6 A 1 1
7 A 1 2
8 A 1 3
9 B 1 1 <- starts over for new factor (Student)
10 B 1 2
11 B 0 0
12 B 1 1
13 B 1 2
14 B 1 3
15 B 1 4
16 B 0 0
17 B 1 1
18 B 1 2
19 B 1 3
20 B 1 4
21 B 1 5
22 B 0 5 <- gets locked at 5
23 B 0 5
24 B 1 6
25 B 1 7
我已经尝试使用庞大的偏移向量矩阵进行此操作。
我尝试使用apply系列功能执行此操作,其中一半不执行任何操作,另一半达到16GB的RAM并使我的计算机崩溃。
我尝试了直接循环,需要4个多小时(这是一个大数据集)
令我困扰的是,这在Excel中是如此容易。通常,R在速度和可写性方面都围绕Excel运转,这使我相信我在这里缺少一些基本知识。
忘记了这个更具挑战性的功能(“锁定在5”),我什至都无法获得重置的累积金额。我无法想到要像这样分组的因素的组合:
Consecutive.Absences = ave(Absent, ..., cumsum)
[显然,按学生分组只会给出总的缺勤情况-它“记住”孩子在缺勤中的缺席,这是由于ave的分裂和重组。
因此,我不知道如何在R中做这件事的核心是:当按行操作时,如何应用可以“查看”前面结果的函数?
在Excel中,这很容易:
C3 = IF($A3=$A2,$B3+$C2,$B3)*$B3
显示此excel功能时没有5位缺失的锁定,易于阅读。
一旦我弄清楚了如何应用一个函数来查看R中相同函数的先前结果,我将能够找出其余的函数。
预先感谢您的帮助-这在我的许多应用程序中将非常有用!
实际上,山姆
更新:谢谢大家提供的有关如何识别学生是否连续5次缺课的想法!
但是,在STUDENTS表的数据库中这样做很容易。我需要知道的是,出勤记录本身中学生连续缺勤的次数,例如“在计算其他汇总统计信息时我们是否会计算出该出勤记录?”
[如果要在使用前一个元素的值的同时将功能应用于向量中的每个元素,则可能需要将累加参数设置为True来检出“ Reduce”
这里是一个例子:
##define your function that takes two parameters
##these are the 'previous' and the 'current' elements
runSum <- function(sum, x){
res = 0
if (x == 1){
res = sum + 1
}
else if (x == 0 & sum < 5){
res = 0
}
else{
res = sum
}
res
}
#lets look at the absent values from subject B
x = c(1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1)
Reduce(x=x, f=runSum, accumulate=T)
# [1] 1 2 0 1 2 3 4 0 1 2 3 4 5 5 5 6 7
[5个或多个奔跑的学生很容易识别:
tapply(dfrm$Absent, dfrm$Student, function(x) rle(x)$value[rle(x)$length >=5] )
$A
integer(0)
$B
[1] 1
在结果中寻找“ 1”的任何值:
tapply(dfrm$Absent, dfrm$Student, function(x) 1 %in% rle(x)$value[rle(x)$length >=5] )
A B
FALSE TRUE
我也一直在努力简化解决方案(但在@kithpradhan方面排在第二位:
ave(dfrm$Absent, dfrm$Student,
FUN= function(XX)
Reduce(function(x,y) if( x[1] >= 5){ y+x[1]
} else{ x[1]*y+y } , #Resets to 0 if y=0
XX, accumulate=TRUE)
)
#[1] 0 1 2 0 0 1 2 3 1 2 0 1 2 3 4 0 1 2 3 4 5 5 5 6 7
作为记录,您也可以创建自己的Reduce
衍生物,该衍生物接收f
和x
,并将f(x)
应用于其输出,直到达到x == f(x)
或maxiter
:
ireduce = function(f, x, maxiter = 50){
i = 1
while(!identical(f(x), x) & i <= maxiter) {x = f(x); i = i+1}; x
}