2017-04-11 57 views
2

考虑:的R - 填补空变量

v1 <- c(1,NA,1,NA,NA) 
v2 <- c(NA,NA,1,NA,1) 
df <- data.frame(rbind(v1, v2)) 

R> df 
X1 X2 X3 X4 X5  
1 NA 1 NA NA 
NA NA 1 NA 1 

我如何填写1之间的'NA'

,使它看起来像这样:

X1 X2 X3 X4 X5 
1 1 1 NA NA 
NA NA 1 1 1 
+0

有多种方法可以做到这一点。你有什么尝试? –

+0

每行只有2列值为1吗?有更多1s的可能性吗?更少1s?在这些情况下你想要什么行为? – A5C1D2H2I1M1N2O1R2T1

+0

只要考虑最简单的情况,其中每行有2个1的值。它们可以相邻(可以保持不变),也可以在两者之间缺少值。谢谢! – kquach

回答

1

我不知道你的数据集有多大,但你可以采取更长的方法,并使用任何一种方法获得更高效的结果e以下:

选项1:使用arr.ind。选项二:使用max.col

myFun2 <- function(indf) { 
    indf2 <- replace(indf, is.na(indf), 0) 
    mins <- max.col(indf2, "first") 
    maxs <- max.col(indf2, "last") 
    L <- Map(seq.int, mins, maxs) 
    mat <- cbind(rep(seq_along(L), lengths(L)), unlist(L, use.names = FALSE)) 
    indf[mat] <- 1 
    indf 
} 
myFun2(df) 

用一些不同大小的数据进行测试。这里有一个方法,使数据:

set.seed(1) 
nc <- 50 
nr <- 10000 
df <- data.frame(t(replicate(nr, sample(c(1, 1, rep(NA, nc-2)))))) 

一些样本输出和时序比较见this Gist

+0

只想说选项2为我工作。谢谢! – kquach

2

我们可以通过该行与applyMARGIN=1循环做到这一点。查找第一个和最后一个非NA元素的索引,并使用第一个非NA元素更改它们之间的元素,转置输出并将其分配回数据集。

df[] <- t(apply(df, 1, function(x) { 
     st <- range(which(!is.na(x))) 
      x[st[1]:st[2]] <- x[st[1]] 
      x})) 
2

另一个apply解决方案上MARGIN=2用的laglead功能的使用从dplyr

library(dplyr) 


v1 <- c(1,NA,1,NA,NA) 
v2 <- c(NA,NA,1,NA,1) 
dff <- data.frame(rbind(v1, v2)) 

apply(t(dff), 2, function(x) { 
    conds <- rowSums(cbind(x, lag(x), lead(x)), na.rm = T)==2 
    x[conds] <- 1 
    x 
}) %>% t() 

输出:

# X1 X2 X3 X4 X5 
# v1 1 1 1 NA NA 
# v2 NA NA 1 1 1 
+0

似乎适用于给定的例子,但不是一般的... – A5C1D2H2I1M1N2O1R2T1

+0

如果有人对我之前的评论感到好奇,请查看https://gist.github.com/mrdwab/048f4323217bade1168a9b3dff521b22。 – A5C1D2H2I1M1N2O1R2T1