如何用 R 中大数据框中的另一个序列替换特定的数字序列(每行)?
How to replace a specific sequence of numbers (per row) with another sequence in a big data frame in R?
我有一个 data.frame,其中包含一组动物的 absence/presence 数据 (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 行(=个人)。
我想做的是用1填充空白(1之间的0),这样上面的数据框就变成了:
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 之后的零不应受到影响。
我浏览了很多 Whosebug 问题,例如:
find and replace numeric sequence in r
但是,我找不到同时适用于所有列、逐行处理的解决方案。
提前感谢您的建议! :)
我们可以按行进行。一个有效的选择是使用 collapse
中的 dapply
。遍历行,找到 1s 的位置索引,得到第一个和最后一个之间的序列,并且 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
和arr.ind = TRUE
获取row/column索引,然后创建序列,并使用row/column索引进行赋值已矢量化
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
使用max.col
在每一行中找到“第一个”和“最后一个”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
使用 apply
-
的基础 R 方法
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
我有一个 data.frame,其中包含一组动物的 absence/presence 数据 (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 行(=个人)。
我想做的是用1填充空白(1之间的0),这样上面的数据框就变成了:
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 之后的零不应受到影响。
我浏览了很多 Whosebug 问题,例如:
find and replace numeric sequence in r
但是,我找不到同时适用于所有列、逐行处理的解决方案。
提前感谢您的建议! :)
我们可以按行进行。一个有效的选择是使用 collapse
中的 dapply
。遍历行,找到 1s 的位置索引,得到第一个和最后一个之间的序列,并且 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
和arr.ind = TRUE
获取row/column索引,然后创建序列,并使用row/column索引进行赋值已矢量化
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
使用max.col
在每一行中找到“第一个”和“最后一个”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
使用 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