我有一个有2列的数据框。
column1中包含随机数 column2是我希望column3看起来像
的地方保留列 random temp
0.502423373 1
0.687594055 0
0.741883739 0
0.445364032 0
0.50626137 0.5
0.516364981 0
...
我想填充column3,因此它取最后一个非零数字(在此示例中为1或.5)并连续用该值填充以下行,直到它遇到具有不同数字的行。然后它重复整个列的过程。
random temp state
0.502423373 1 1
0.687594055 0 1
0.741883739 0 1
0.445364032 0 1
0.50626137 0.5 0.5
0.516364981 0 0.5
0.807804708 0 0.5
0.247948445 0 0.5
0.46573337 0 0.5
0.103705154 0 0.5
0.079625868 1 1
0.938928944 0 1
0.677713019 0 1
0.112231619 0 1
0.165907178 0 1
0.836195267 0 1
0.387712998 1 1
0.147737077 0 1
0.439281543 0.5 0.5
0.089013503 0 0.5
0.84174743 0 0.5
0.931738707 0 0.5
0.807955172 1 1
感谢任何和所有帮助
答案 0 :(得分:11)
将值“0”设置为na.locf
后,也许可以使用“zoo”包中的NA
。假设您的data.frame
被称为“mydf”:
mydf$state <- mydf$temp
mydf$state[mydf$state == 0] <- NA
library(zoo)
mydf$state <- na.locf(mydf$state)
# random temp state
# 1 0.5024234 1.0 1.0
# 2 0.6875941 0.0 1.0
# 3 0.7418837 0.0 1.0
# 4 0.4453640 0.0 1.0
# 5 0.5062614 0.5 0.5
# 6 0.5163650 0.0 0.5
如果“temp”列中的原始NA
中有data.frame
个值,并且您希望将它们保留为新生成的“州”列中的NA
,那就是容易照顾。只需添加一行即可重新引入NA
值:
mydf$state[is.na(mydf$temp)] <- NA
答案 1 :(得分:5)
受@Ananda Mahto解决方案的启发,这是对na.locf
的内部代码的改编,它直接与0
代替NA
s。那么您不需要zoo
包,也不需要进行将值更改为NA
的预处理。基准测试显示,这比原始版本快约10倍。
locf.0 <- function(x) {
L <- x!=0
idx <- c(0, which(L))[cumsum(L) + 1]
return(x[idx])
}
mydf$state <- locf.0(mydf$temp)
答案 2 :(得分:3)
这是Reduce
函数的一种有趣方式。
temp = c(1,0,0,0,.5,0,0,0,0,0,1,0,0,0,0,0,1,0,0.5,0,0,0,1)
fill_zero = function(x,y) if(y==0) x else y
state = Reduce(fill_zero, temp, accumulate=TRUE)
如果您担心速度,可以试试Rcpp。
library(Rcpp)
cppFunction('
NumericVector fill_zeros( NumericVector x ) {
for( int i=1; i<x.size(); i++ )
if( x[i]==0 ) x[i] = x[i-1];
return x;
}
')
state = fill_zeros(temp)
答案 3 :(得分:3)
另外,除非我忽视某些事情,否则这似乎有效:
DF$state2 <- ave(DF$temp, cumsum(DF$temp), FUN = function(x) x[x != 0])
DF
# random temp state state2
#1 0.50242337 1.0 1.0 1.0
#2 0.68759406 0.0 1.0 1.0
#3 0.74188374 0.0 1.0 1.0
#4 0.44536403 0.0 1.0 1.0
#5 0.50626137 0.5 0.5 0.5
#6 0.51636498 0.0 0.5 0.5
#7 0.80780471 0.0 0.5 0.5
#8 0.24794844 0.0 0.5 0.5
#9 0.46573337 0.0 0.5 0.5
#10 0.10370515 0.0 0.5 0.5
#11 0.07962587 1.0 1.0 1.0
#12 0.93892894 0.0 1.0 1.0
#13 0.67771302 0.0 1.0 1.0
#14 0.11223162 0.0 1.0 1.0
#15 0.16590718 0.0 1.0 1.0
#16 0.83619527 0.0 1.0 1.0
#17 0.38771300 1.0 1.0 1.0
#18 0.14773708 0.0 1.0 1.0
#19 0.43928154 0.5 0.5 0.5
#20 0.08901350 0.0 0.5 0.5
#21 0.84174743 0.0 0.5 0.5
#22 0.93173871 0.0 0.5 0.5
#23 0.80795517 1.0 1.0 1.0
答案 4 :(得分:0)
沿着以下几行的循环应该可以帮到你 -
for(i in seq(nrow(df)))
{
if (df[i,"v1"] == 0) df[i,"v1"] <- df[i-1,"v1"]
}
输出 -
> df
v1 somedata
1 1 33
2 2 24
3 1 36
4 0 49
5 2 89
6 2 48
7 0 4
8 1 98
9 1 60
10 2 76
>
> for(i in seq(nrow(df)))
+ {
+ if (df[i,"v1"] == 0) df[i,"v1"] <- df[i-1,"v1"]
+ }
> df
v1 somedata
1 1 33
2 2 24
3 1 36
4 1 49
5 2 89
6 2 48
7 2 4
8 1 98
9 1 60
10 2 76
答案 5 :(得分:0)
我建议使用行程编码函数,这是处理数据集中的牛排的一种自然方式。使用@ Kevin的示例向量:
temp = c(1,0,0,0,.5,0,0,0,0,0,1,0,0,0,0,0,1,0,0.5,0,0,0,1)
y <- rle(temp)
#str(y)
#List of 2
# $ lengths: int [1:11] 1 3 1 5 1 5 1 1 1 3 ...
# $ values : num [1:11] 1 0 0.5 0 1 0 1 0 0.5 0 ...
# - attr(*, "class")= chr "rle"
for( i in seq(y$values)[-1] ) {
if(y$values[i] == 0) {
y$lengths[i-1] = y$lengths[i] + y$lengths[i-1]
y$lengths[i] = 0
}
}
#str(y)
#List of 2
# $ lengths: num [1:11] 4 0 6 0 6 0 2 0 4 0 ...
# $ values : num [1:11] 1 0 0.5 0 1 0 1 0 0.5 0 ...
# - attr(*, "class")= chr "rle"
inverse.rle(y)
# [1] 1.0 1.0 1.0 1.0 0.5 0.5 0.5 0.5 0.5 0.5 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 0.5
# [20] 0.5 0.5 0.5 1.0
答案 6 :(得分:-1)
只需使用带有全局变量的循环,
此处使用的全局变量为m
,r
是具有两列A
和B
的数据框。
r$B = c(1,NA, NA, NA, 3, NA,6)
m=1
for( i in 1:nrow(r) ){
if(is.na(r$B[i])==FALSE ){
m <<- i # please note the assign sign , " <<- "
next()
} else {
r$B[i] = r$B[m]
}
}
执行后:
r$B = 1 1 1 1 3 3 6