5

如何应用在按行操作时可以“看到”前面结果的函数?

这出现了很多,但我目前的问题需要学生的运行总数,如果总数没有达到 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”)功能,我什至无法获得重置的 cumsum。我无法想到像这样对 ave 进行分组的因素组合:

Consecutive.Absences = ave(Absent, ..., cumsum)

显然,对学生进行分组只会给出总累积缺勤 - 它“记住”孩子因 ave 中的拆分和重组而缺席的间隙。

所以正如我所说,我在 R 中不知道该怎么做的核心是:
如何应用一个在按行操作时可以“看到”前面结果的函数?

在 Excel 中很容易:

C3 = IF($A3=$A2,$B3+$C2,$B3)*$B3

此 excel 函数显示时没有 5-absence 锁定,以便于阅读。

一旦我弄清楚如何应用一个函数来查看 R 中相同函数的先前结果,我将能够找出其余的。

提前感谢您的帮助——这在我的许多应用程序中都非常有用!

真的,山姆


更新:
谢谢大家关于如何识别学生是否连续缺勤 5 次的想法!

但是,这在 STUDENTS 表的数据库中很容易做到。我需要知道的是学生在出勤记录本身中连续缺勤的次数,例如“我们在计算其他汇总统计数据时是否计算这个特定的出勤记录?”

4

3 回答 3

8

如果您希望在使用前一个元素的值的同时将函数应用于向量中的每个元素,您可能需要查看“Reduce”,并将累积参数设置为 True

这是一个例子:

##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
于 2013-04-15T21:02:52.243 回答
1

识别一次或多次运行 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
于 2013-04-15T20:52:06.117 回答
0

作为记录,您还可以创建自己的Reduce-derivative 接收fand x,并应用于f(x)其输出,直到达到x == f(x)or maxiter

ireduce = function(f, x, maxiter = 50){
  i = 1
  while(!identical(f(x), x) & i <= maxiter) {x = f(x); i = i+1}; x
}
于 2020-03-26T10:21:09.627 回答