我有以下数据集:
> df
A B C
[1,] 1 0 0
[2,] 1 0 0
[3,] 1 0 0
[4,] 1 0 1
[5,] 1 0 1
[6,] 1 0 1
[7,] 1 0 1
[8,] 1 0 0
[9,] 0 0 0
[10,] 0 0 0
[11,] 0 0 0
[12,] 0 0 0
[13,] 0 0 0
我想对每一列做两件事:首先,我想要将0到0的两个位置内的所有1改变为0.然后,我想选择至少有四个连续的列的区域1秒;换句话说,如果出现一个不在四个或更多1的连续字符串中的1,它将变为0.结果数据集应如下所示:
(a.T @ b).size
(a @ b.T).size
最好的方法是什么?谢谢!
答案 0 :(得分:1)
这是使用base
函数的另一种可能方法。内联代码的解释。
apply(df, 2, function(x) {
#identify 0 locations, create indices 2 places away from these locations
#and set these to 0
idx <- unique(unlist(lapply(which(x==0L), `+`, -2L:2L)))
x[idx[idx > 0L & idx <= length(x)]] <- 0L
#create run length encoding, filter for those with value=1 but less than 4
#and set those lengths to 0
r <- rle(x)
r$values[r$lengths < 4L & r$values==1L] <- 0L
inverse.rle(r)
})
输出:
A B C
[1,] 1 0 0
[2,] 1 0 0
[3,] 1 0 0
[4,] 1 0 1
[5,] 1 0 1
[6,] 1 0 1
[7,] 1 0 1
[8,] 1 0 0
[9,] 0 0 0
[10,] 0 0 0
[11,] 0 0 0
[12,] 0 0 0
[13,] 0 0 0
答案 1 :(得分:0)
您可以使用lag
和lead
进行比较(第一部分)。
以下是使用您的数据的示例(在对您的问题进行任何修改之前,这是在原始版本上):
library(dplyr)
library(tidyverse)
df <-
as.tibble(df) %>%
mutate(A_lag=lag(A)) %>%
mutate(B_lag=lag(B)) %>%
mutate(C_lag=lag(C)) %>%
mutate(A_lag2=lag(A,2)) %>%
mutate(B_lag2=lag(B,2)) %>%
mutate(C_lag2=lag(C,2)) %>%
mutate(A_lead=lead(A)) %>%
mutate(B_lead=lead(B)) %>%
mutate(C_lead=lead(C)) %>%
mutate(A_lead2=lead(A,2)) %>%
mutate(B_lead2=lead(B,2)) %>%
mutate(C_lead2=lead(C,2)) %>%
as.data.frame()
a <- df[,c(1,4,7,10,13)]
b <- df[,c(2,5,8,11,14)]
c <- df[,c(3,6,9,12,15)]
df <- data.frame(A=apply(a,1,min,na.rm=T),
B=apply(b,1,min,na.rm=T),
C=apply(c,1,min,na.rm=T)
)
这会产生一个如下所示的中间结果表:
A B C 1 1 0 0 2 1 0 0 3 1 0 0 4 1 0 1 5 1 0 1 6 1 0 1 7 1 0 1 8 1 0 0 9 0 0 0 10 0 1 0 11 0 1 0 12 0 1 0 13 0 1 0
此步骤的结果符合您的逻辑。
然而,下一步似乎你的话要求一件事 - 只保留1个在至少四个1的列式块中 - 但你的例子显示略有不同。
您的示例输出将列B
显示为全0,即使最后4行由于前一步骤的逻辑而全部为1。
我已经创建了一些遵循您指定的逻辑的代码。如果您忘记包含细节或者想要稍微不同的东西,这应该会让您足够接近(否则请在评论中告诉我)。
# You could do it without a for loop if need be
myfun <- function(x) {
for(i in 1:length(x)){
x[i] <- ifelse((sum(x[i:(max(0,i-3))]) == 4) | (sum(x[i:(min(length(x),i+3))]) == 4),1,0)
}
return(x)
}
apply(df,2,myfun)