Reputation: 61
I have a data frame with large number of columns, each row has a bunch of -1 values and I only want to retain the values in a row that are not -1. For example, if my data is:
A1 A2 A3 A4 A5
-1 -1 2 -1 6
2 -1 -1 -1 -1
4 -1 -1 -1 3
6 5 -1 2 2
I want the output to extract all the values in a row apart from -1 to other variables, say:
V1 V2 V3 V4
2 6
2
4 3
6 5 2 2
Row 1 and row 3 have two values that are not -1 so these two values will be moved V1 and V2 and then V3 and V4 become empty. Row 2 has 1 value so it occupies V1 so V2, V3 and V4 will be empty for this row. Row 4 has four values that are not -1. Then all these values will be occupied in new variables V1 to V4.
Upvotes: 1
Views: 560
Reputation: 886938
Looks like we can do this with apply
Filter(function(x) !all(is.na(x)), as.data.frame(t(apply(df1, 1,
function(x) c(x[x!= -1], rep(NA, sum(x == -1)))))))
# V1 V2 V3 V4
#1 2 6 NA NA
#2 2 NA NA NA
#3 4 3 NA NA
#4 6 5 2 2
Upvotes: 1
Reputation: 39154
dt2
is the final output.
# Create example data frame
dt <- read.table(text = "A1 A2 A3 A4 A5
-1 -1 2 -1 6
2 -1 -1 -1 -1
4 -1 -1 -1 3
6 5 -1 2 2",
header = TRUE)
# Replace -1 with NA
dt[dt == -1] <- NA
# Sort each row in the data frame, the result is a list
dt_list <- apply(dt, 1, sort)
# Find the maximum length of each row with non-NA values
max_len <- max(sapply(dt_list, length))
# Add NA based on the length of each row
dt_list2 <- lapply(dt_list, function(x){
if (length(x) < max_len){
x <- c(x, rep(NA, max_len - length(x)))
}
return(x)
})
# Combine all rows, create a new data frame
dt2 <- as.data.frame(do.call(rbind, dt_list2))
# Change the column name
colnames(dt2) <- paste0("V", 1:ncol(dt2))
dt2
V1 V2 V3 V4
1 2 6 NA NA
2 2 NA NA NA
3 3 4 NA NA
4 2 2 5 6
Upvotes: 0
Reputation: 479
con <- textConnection("
A1 A2 A3 A4 A5
-1 -1 2 -1 6
2 -1 -1 -1 -1
4 -1 -1 -1 3
6 5 -1 2 2")
df <- read.delim(con, sep = " ")
df2 <- df
df2[,] <- ""
m <- 0
for(i in 1:nrow(df)) {
x <- df[i,][df[i,] != -1]
df2[i,1:length(x)] <- x
m <- max(m, length(x))
}
df2 <- df2[, 1:m]
colnames(df2) <- paste0("V", 1:m)
df2
# V1 V2 V3 V4
# 1 2 6
# 2 2
# 3 4 3
# 4 6 5 2 2
Upvotes: 1