我有一个数据帧,其中包含100.000行。它看起来像这样:
Value
1
2
-1
-2
0
3
4
-1
3
我想创建一个额外的列(B列)。其中包括0和1。
它基本上是0,但是当一行中有5个数据点为正或负时,则应该给出1.但是,只有当它们在一行中时(例如:当行是正数时,有负数......计数应重新开始)。
Value B
1 0
2 0
1 0
2 0
2 1
3 1
4 1
-1 0
3 0
我尝试了不同的循环,但它没有用。我还尝试将整个DF转换为列表(并在列表上循环)。不幸的是没有尽头。
答案 0 :(得分:1)
这是一种使用rollmean
包中的zoo
函数的方法。
set.seed(1000)
df = data.frame(Value = sample(-9:9,1000,replace=T))
sign = sign(df$Value)
library(zoo)
rolling = rollmean(sign,k=5,fill=0,align="right")
df$B = as.numeric(abs(rolling) == 1)
我生成了1000个正值和负值的值。
sign
- 这对于负数为-1,对于正数为1,对于0为0 注意 - 不需要循环。这一切都可以进行矢量化(一旦我们计算了滚动平均值)。
答案 1 :(得分:0)
这会奏效。这不是最有效的方法,但逻辑非常透明 - 只需检查五个相邻行的每个序列是否只有一个唯一的符号(即+, - 或0):
dat <- data.frame(Value=c(1,2,1,2,2,3,4,-1,3))
dat$new_col <- NA
dat$new_col[1:4] <- 0
for (x in 5:nrow(dat)){
if (length(unique(sign(dat$Value[(x-4):x])))==1){
dat$new_col[x] <- 1
} else {
dat$new_col[x] <- 0
}
}
答案 2 :(得分:0)
使用cumsum(...diff(...) <condition>)
惯用法创建分组变量,使用ave
计算每个组中的索引。
d$B2 <- ave(d$Value, cumsum(c(0, diff(sign(d$Value)) != 0)), FUN = function(x){
as.integer(seq_along(x) > 4)})
# Value B B2
# 1 1 0 0
# 2 2 0 0
# 3 1 0 0
# 4 2 0 0
# 5 2 1 1
# 6 3 1 1
# 7 4 1 1
# 8 -1 0 0
# 9 3 0 0