我的数据包含一个id变量,然后是多个访问变量,用于跟踪人们随时间的分数。我正在尝试将分数向前推进,将任何后续零点更新为该分数。如果有NA,我想留下它(代表没有访问),如果一个人稍后获得新分数,我希望新分数继续发展。
我已经包含了一个可重复的小例子,但我的实际数据非常大,因此不能手动更新。我目前的尝试是使用for循环遍历每个人(行)的访问列。但是我收到了这个警告:
if((!is.na(first)& first!= 0)&(!is.na(second)& second ==)出错 参数长度为零 另外:警告信息: 在is.na(第二个)中:is.na()应用于类型为' NULL'
的非(列表或向量)看起来是因为在环境(Rstuio)中,第一个值为NA_real_,第二个值为NULL(空)。
如何正确定义这些? 我没有太多的for循环经验,欢迎大家提出建议!
id <- c(101, 102, 103, 104)
visit.1 <- c(0, 21, 0, 21)
visit.2 <- c(0, 0, 50, 0)
visit.3 <- c(0, 0, 0, 44)
visit.4 <- c(NA, NA, 0, 0)
dat <- data.frame(id, visit.1, visit.2, visit.3, visit.4)
for(i in 1:nrow(dat)){
for(j in 2:ncol(dat)){
first <- dat[i, j]
second <- dat[i,(j+1)]
if((!is.na(first) & first != 0) & (!is.na(second) & second == 0)){
second <- first
} else {
second <- second
}
}
}
原始数据集:
id visit.1 visit.2 visit.3 visit.4
1 101 0 0 0 NA
2 102 21 0 0 NA
3 103 0 50 0 0
4 104 21 0 44 0
期望的最终结果:
id visit.1 visit.2 visit.3 visit.4
1 101 0 0 0 NA
2 102 21 21 21 NA
3 103 0 50 50 50
4 104 21 21 44 44
答案 0 :(得分:3)
一种非常简单的方法是消除内部循环并对内部替换循环进行矢量化。这不是最好的解决方案,但更接近您更熟悉的内容:
id <- c(101, 102, 103, 104)
visit.1 <- c(0, 21, 0, 21)
visit.2 <- c(0, 0, 50, 0)
visit.3 <- c(0, 0, 0, 44)
visit.4 <- c(NA, NA, 0, 0)
dat <- data.frame(id, visit.1, visit.2, visit.3, visit.4)
for (index in 3:5){
dat[[index]]<-ifelse(dat[[index]]==0, dat[[index-1]], dat[[index]])
}
我正在使用for循环从列移动到列。然后ifelse正在查看整个列。对于== 0的行,如果不使用当前值,则使用左侧的值。
答案 1 :(得分:2)
Dave2e用更少的代码行回答了你的问题,但我稍微修改了你的尝试,以便你可以看到你做错了什么:
from flask import Flask
app = Flask(__name__)
app.config['DEBUG'] = False
@app.route('/test')
def test():
return 'hello world'
首先使用for(i in 1:nrow(newdat)){
for(j in 3:ncol(newdat)) {
first <- newdat[i, j-1]
second <- newdat[i, j]
if(!is.na(first) & !is.na(second) & second == 0){
newdat[i,j] <- first
}
}
}
您在dat[i,(j+1)]
中计算得太多,所以我使用了for(j in 2:ncol(dat)){ ... }
并设置了3:ncol(dat)
。
其次first <- newdat[i, j-1]
无法正常工作,您需要直接处理数据框。
答案 2 :(得分:1)
zoo::na.locf
可以在这里使用
library(zoo)
data <- tail(t(dat), -1)
# [,1] [,2] [,3] [,4]
# visit.1 0 21 0 21
# visit.2 0 0 50 0
# visit.3 0 0 0 44
# visit.4 NA NA 0 0
placeholder_value <- function(mat) {
head(setdiff(seq(0, max(c(mat), na.rm=TRUE), 1), unique(c(mat))), 1)
}
val <- placeholder_value(data)
由于na.locf
会搜索要归待的NA
值,因此NA
值会在运行na.locf
之前更改为占位符值(并且0
更改为{ {1}}),然后将这些值转换回原始值。
NA
答案 3 :(得分:1)
另一个基础R方法将是我们ave
cbind(dat[1],t(apply(dat[-1],1,function(x)ave(x,cumsum(x),FUN=sum))))
id visit.1 visit.2 visit.3 visit.4
1 101 0 0 0 NA
2 102 21 21 21 NA
3 103 0 50 50 50
4 104 21 21 44 44
data.table
格式。没有涉及循环:
library(data.table)
A=setDT(melt(dat,1))[,.(variable,ave(value,cumsum(value),FUN=sum)),by=id]
dcast(A,id~variable,value.var = "V2")
id visit.1 visit.2 visit.3 visit.4
1 101 0 0 0 NA
2 102 21 21 21 NA
3 103 0 50 50 50
4 104 21 21 44 44