As shown below, let's assume we have a data frame with 1 'extent' column, and 10 'col' columns, of which only first 7 'cols' are filled in the beginning.
Note: Grey highlight in NA cells is just for aesthetics.
We need to move first 'extent' cells of col columns to the end by some vectorised formula or a function. The output should look like below:
I wrote following piece of code to do it, but it's not working:
df <- ifelse(df$extent > 0,
df[, c(1, 9:(9 df$extent), 2 df$extent:8,2:(1 df$extent),(9 df$extent):11)
] ,df)
I get the error as: "numerical expression has 3 elements: only the first used"
Please help me out.
CodePudding user response:
Using a for
loop and a swap
function :
dat <- structure(list(extent = 0:2, col1 = c("1", "A", "a"), col2 = c("2", "B", "b"), col3 = c("3", "C", "c"), col4 = c("4", "D", "d"), col5 = c("5", "E", "e"), col6 = c("6", "F", "f"), col7 = c("7", "G", "g"), col8 = c(NA, NA, NA), col9 = c(NA, NA, NA), col10 = c(NA, NA, NA)), row.names = c(NA, -3L), class = "data.frame")
for (i in 1:nrow(dat)) {
k <- 7 #number of non NA cols
ext <- dat$extent[i]
if(ext > 0) seqinr::swap(dat[i, 2:(ext 1)], dat[i, (k 2):(k ext 1)])
}
dat
CodePudding user response:
Inefficient, but a start:
myshift <- function(x, n = 1) { if (!length(x) || n == 0) return(x); x[(seq_along(x) - n - 1) %% length(x) 1]; }
dat[-1] <- do.call(rbind, Map(function(z, n) myshift(z, n), asplit(as.matrix(dat[-1]), 1), dat$extent))
dat
# extent V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
# 1 0 1 2 3 4 5 6 7 <NA> <NA> <NA>
# 2 1 <NA> A B C D E F G <NA> <NA>
# 3 2 <NA> <NA> a b c d e f g <NA>
Data
dat <- structure(list(extent = 0:2, V1 = c("1", "A", "a"), V2 = c("2", "B", "b"), V3 = c("3", "C", "c"), V4 = c("4", "D", "d"), V5 = c("5", "E", "e"), V6 = c("6", "F", "f"), V7 = c("7", "G", "g"), V8 = c(NA, NA, NA), V9 = c(NA, NA, NA), V10 = c(NA, NA, NA)), row.names = c(NA, -3L), class = "data.frame")