Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

As to data.frame,how to loop column name first and then loop row name of column?

Tags:

r

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?

like image 857
kittygirl Avatar asked Jan 30 '26 22:01

kittygirl


2 Answers

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"  
like image 68
akrun Avatar answered Feb 02 '26 13:02

akrun


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)
like image 20
Ronak Shah Avatar answered Feb 02 '26 14:02

Ronak Shah



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!