Reputation: 403
I have a question on how to use the paste
function in a list if its vectors are of different lengths. I have a dataframe with columns of different lengths, such as:
df = data.frame(Set1=c("abc",'def',"ghi","jkl",""), Set2=c("abc",'def',"","",""), Set3=c("mno","pqr","stu","vwx","xyz"))
I tried to make a list a.list
based on each column and collapse each factor with a ,
. Something like
a.list
$Set1
[1] abc,def,ghi,jkl
$Set2
[1] abc,def
$Set3
[1] mno,pqr,stu,vwx,xyz
I tried
> a.list = apply(df, 2, as.list)
> a.list = lapply(a.list, function(x) paste(x, collapse=",")
However, it collapsed the factors with ,
to the maximum length of the list. For example,
a.list
$Set1
[1] "abc,def,ghi,jkl,"
$Set2
[1] "abc,def,,,"
Sorry it may be a simple question. I am still learning R. Thanks!
Upvotes: 2
Views: 195
Reputation: 887213
We can remove the ''
with setdiff
after looping over the columns with lapply
, then paste
the rest of the elements (toString
). Note that toString
=> paste(..., collapse=", ")
lapply(df, function(x) toString(setdiff(x, '')))
This assumes that there are unique
elements in the column. If there are duplicates, use vsetdiff
library(vecsets)
lapply(df, function(x) toString(vsetdiff(x, '')))
Or using nzchar
lapply(df, function(x) toString(x[nzchar(x)]))
#$Set1
#[1] "abc, def, ghi, jkl"
#$Set2
#[1] "abc, def"
#$Set3
#[1] "mno, pqr, stu, vwx, xyz"
Also, it may be better to return a vector
instead of list
as each element of the list
is of length
1
sapply(df, function(x) toString(x[nzchar(x)]))
Or using tidyverse
library(dplyr)
library(stringr)
df %>%
summarise(across(everything(), ~ str_c(.[nzchar(.)], collapse=",")))
NOTE: We don't need to create a logical vector with !=
as nzchar
already does that
Upvotes: 1
Reputation: 389012
You can remove the empty values from each element in the list and paste
the values.
lapply(df, function(x) paste(x[x!=''], collapse = ","))
#$Set1
#[1] "abc,def,ghi,jkl"
#$Set2
#[1] "abc,def"
#$Set3
#[1] "mno,pqr,stu,vwx,xyz"
Upvotes: 1