Reputation: 854
I have a data frame that looks like this:
df <- read.table(tc <- textConnection("
var1 var2 var3 var4
1 2 7 NA
4 4 NA 6
2 NA 3 NA
4 4 4 4
1 3 NA NA"), header = TRUE); close(tc)
I want to replace the penultimate non-empty row tails with NAs to give me a new data frame that looks like this:
df <- read.table(tc <- textConnection("
var1 var2 var3 var4
1 NA 7 NA
4 NA NA 6
NA NA 3 NA
4 4 NA 4
NA 3 NA NA"), header = TRUE); close(tc)
I'm able to identify the location of the penultimate non-empty row tails by using the statement:
penultimate <- function(x) head(tail(x[!is.na(x)], 2),1)
My problem is how to now change these to NAs.
Upvotes: 1
Views: 178
Reputation: 887118
We can use apply
penultimate <- function(x) replace(x, head(tail(which(!is.na(x)), 2),1), NA)
t(apply(df, 1, penultimate))
# var1 var2 var3 var4
#[1,] 1 NA 7 NA
#[2,] 4 NA NA 6
#[3,] NA NA 3 NA
#[4,] 4 4 NA 4
#[5,] NA 3 NA NA
Or we can use which
with arr.ind=TRUE
i1 <- which(!is.na(df), arr.ind=TRUE)
df[i1[!!ave(i1[,2], i1[,1], FUN = function(x) rank(-x)==2),]] <- NA
If we need to use dplyr
, the rowwise
with do
can get the expected output
library(dplyr)
df %>%
rowwise() %>%
do(data.frame(t(penultimate(unlist(.)))))
# var1 var2 var3 var4
# <int> <int> <int> <int>
#1 1 NA 7 NA
#2 4 NA NA 6
#3 NA NA 3 NA
#4 4 4 NA 4
#5 NA 3 NA NA
Or using data.table
library(data.table)
setDT(df)[, as.list(penultimate(unlist(.SD))), .(rn= 1:nrow(df))][, rn := NULL][]
Upvotes: 2