5

我有一个数据框,其中包含一组动物的缺席/在场数据(0/1),列为年份,行为个体。

我的数据:

df <- data.frame(Year1 = c('1','0','0','0','0','0'),
                 Year2 = c('1','1','1','0','0','0'),
                 Year3 = c('1','1','1','1','1','0'),
                 Year4 = c('0','1','0','0','0','1'),
                 Year5 = c('0','0','1','1','0','1'),
                 Year6 = c('0','0','0','1','1','1'))

df
     Year1 Year2 Year3 Year4 Year5 Year6
1:     1     1     1     0     0     0
2:     0     1     1     1     0     0
3:     0     1     1     0     1     0
4:     0     0     1     0     1     1
5:     0     0     1     0     0     1
6:     0     0     0     1     1     1

有些人有视力差距(一年看到(1),然后第二年没有看到(0),但在第三年再次发现(1))。总共有 400 行(=个人)。

我想要做的是用1s填充空白(1s之间的0s),这样上面的数据框就变成了:

df
     Year1 Year2 Year3 Year4 Year5 Year6
1:     1     1     1     0     0     0
2:     0     1     1     1     0     0
3:     0     1     1     1     1     0
4:     0     0     1     1     1     1
5:     0     0     1     1     1     1
6:     0     0     0     1     1     1

第一个 1 之前和最后一个 1 之后的零不应受到影响。

我浏览了许多stackoverflow问题,例如:

在r中查找和替换数字序列

根据前面的值按组替换一系列值

但是,我无法找到一种可以逐行同时跨所有列工作的解决方案。

提前感谢您的建议!:)

4

3 回答 3

7

用于max.col查找每行中的“first”和“last” 1,然后与col()umn号进行比较:

df[col(df) >= max.col(df, "first") & col(df) <= max.col(df, "last")] <- 1
df

#  Year1 Year2 Year3 Year4 Year5 Year6
#1     1     1     1     0     0     0
#2     0     1     1     1     0     0
#3     0     1     1     1     1     0
#4     0     0     1     1     1     1
#5     0     0     1     1     1     1
#6     0     0     0     1     1     1
于 2021-10-10T22:33:32.347 回答
3

我们可以逐行进行。一个有效的选择是使用dapplyfrom collapse。遍历行,找到 1 的位置索引,得到第一个和最后一个之间的序列,以及replace那些元素为 1。

library(collapse)
dapply(df, MARGIN = 1, FUN = function(x)
     replace(x,  do.call(`:`, as.list(range(which(x == 1)))),  1 ))

-输出

  Year1 Year2 Year3 Year4 Year5 Year6
1     1     1     1     0     0     0
2     0     1     1     1     0     0
3     0     1     1     1     1     0
4     0     0     1     1     1     1
5     0     0     1     1     1     1
6     0     0     0     1     1     1

which一种选择是使用and获取行/列索引arr.ind = TRUE,然后创建序列,并使用行/列索引进行矢量化分配

ind <- which(df ==1, arr.ind = TRUE)
m1 <- as.matrix(transform(stack(lapply(split(ind[,2], ind[,1]), 
   function(x) x[1]:x[length(x)]))[2:1], ind = as.integer(ind)))
df[m1] <- 1
于 2021-10-10T22:18:54.340 回答
0

基础 R 中的一种方法,使用apply-

df[] <- t(apply(df, 1, function(x) {
  rg <- range(which(x == 1))
  x[rg[1]:rg[2]] <- 1
  x
}))

df

#  Year1 Year2 Year3 Year4 Year5 Year6
#1     1     1     1     0     0     0
#2     0     1     1     1     0     0
#3     0     1     1     1     1     0
#4     0     0     1     1     1     1
#5     0     0     1     1     1     1
#6     0     0     0     1     1     1
于 2021-10-11T03:50:37.650 回答