df <- data.frame(
cola = c("A","C",NA,"C"),
colb = c("A",NA,NA,"D"),
colc = c(NA,5,3,NA),
stringsAsFactors = FALSE
)
cola colb colc
1 A A NA
2 C <NA> 5
3 <NA> <NA> 3
4 C D NA
I want to print colnames first,then rownames when cell vaue is not NA,get the expect output as below:
cola=1+2+4
colb=1+4
colc=2+3
Then I tried :
df %>%
lapply(function(x){
r_name=list()
for(i in x){if(!is.na(i)) {r_name<-list(r_name,rownames(i))}}
paste0(colnames(x),'=',paste(r_name,collapse='+'))
}
)
But output is:
$cola
[1] "=list(list(list(), NULL), NULL)+NULL"
$colb
[1] "=list(list(), NULL)+NULL"
$colc
[1] "=list(list(), NULL)+NULL"
Where is the problem?
We loop over the columns of dataset with sapply, get the index of non-NA elements, use that to subset the row.names, paste the elements by collapseing with + and paste with the column names of 'df' with the output of sapply
paste(names(df), sapply(df, function(x)
paste(row.names(df)[which(!is.na(x))], collapse="+")), sep="=")
#[1] "cola=1+2+4" "colb=1+4" "colc=2+3"
Or with which/arr.ind
i1 <- which(!is.na(df), arr.ind = TRUE)
paste(names(df), tapply(row.names(df)[i1[,1]], i1[,2],
FUN = paste, collapse="+"), sep="=")
#[1] "cola=1+2+4" "colb=1+4" "colc=2+3"
Or with imap
library(purrr)
library(stringr)
unname(imap_chr(df, ~ str_c(.y, "=",
str_c(row.names(df)[!is.na(.x)], collapse='+'))))
#[1] "cola=1+2+4" "colb=1+4" "colc=2+3"
You can iterate over the column names, subset them from the dataframe, get the indices of non-NA values and paste them together along with column name.
sapply(names(df), function(x) paste0(x, ' = ',
paste0(which(!is.na(df[, x])), collapse = '+')), USE.NAMES = FALSE)
#[1] "cola = 1+2+4" "colb = 1+4" "colc = 2+3"
Similar using mapply :
mapply(function(x, y) paste0(x, ' = ', paste0(which(!is.na(y)), collapse = '+')),
names(df), df, USE.NAMES = FALSE)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With