1

I want to coerce all columns for multiple data.frames to character in order to rbind them later. The problem is I can't create the appropriate function to use it within lapply.

# Fake dataset
set.seed(123)
A = as.data.frame(matrix(sample(c('NA',1:10),10*10,T),10))
B = as.data.frame(matrix(sample(c('NA',LETTERS[1:10]),10*10,T),10))
C = as.data.frame(matrix(sample(c('NA',letters[1:10]),10*10,T),10))

In principle, this task should be as simple as:

target = list(A, B, C)
lapply(target, function(x) {
  x <- as.character(x)
}) -> df

But, when I run str(df), I get this:

List of 3
 $ : chr [1:10] "c(\"2\", \"2\", \"9\", \"1\", \"5\", \"10\", \"4\", \"3\", \"5\", \"8\")" "c(\"9\", \"10\", \"4\", \"2\", \"10\", \"8\", \"8\", \"8\", \"2\", \"7\")" "c(\"9\", \"6\", \"9\", \"8\", \"2\", \"3\", \"NA\", \"10\", \"6\", \"4\")" "c(\"9\", \"6\", \"8\", \"8\", \"9\", \"6\", \"10\", \"4\", \"6\", \"4\")" ...
 $ : chr [1:10] "c(\"G\", \"B\", \"G\", \"NA\", \"F\", \"J\", \"F\", \"F\", \"I\", \"E\")" "c(\"F\", \"J\", \"I\", \"D\", \"E\", \"G\", \"D\", \"F\", \"J\", \"C\")" "c(\"B\", \"H\", \"F\", \"E\", \"I\", \"H\", \"F\", \"A\", \"B\", \"G\")" "c(\"C\", \"F\", \"C\", \"NA\", \"G\", \"C\", \"H\", \"G\", \"E\", \"J\")" ...
 $ : chr [1:10] "c(\"h\", \"h\", \"d\", \"f\", \"e\", \"j\", \"NA\", \"i\", \"i\", \"NA\")" "c(\"i\", \"

Next try is with:

lapply(target, function(x,i) {
    x[,i] <- as.character(x[,i])
return(x)}) -> df

This returns 3 data.frames as expected but the str is not what I want (partial output for first data.frame):

 $ :'data.frame':       10 obs. of  10 variables:
  ..$ V1 : chr [1:10] "c(\"2\", \"2\", \"9\", \"1\", \"5\", \"10\", \"4\", \"3\", \"5\", \"8\")" "c(\"9\", \"10\", \"4\", \"2\", \"10\", \"8\", \"8\", \"8\", \"2\", \"7\")" "c(\"9\", \"6\", \"9\", \"8\", \"2\", \"3\", \"NA\", \"10\", \"6\", \"4\")" "c(\"9\", \"6\", \"8\", \"8\", \"9\", \"6\", \"10\", \"4\", \"6\", \"4\")" ...
  ..$ V2 : chr [1:10] "c(\"2\", \"2\", \"9\", \"1\", \"5\", \"10\", \"4\", \"3\", \"5\", \"8\")" "c(\"9\", \"10\", \"4\", \"2\", \"10\", \"8\", \"8\", \"8\", \"2\", \"7\")" "c(\"9\", \"6\", \"9\", \"8\", \"2\", \"3\", \"NA\", \"10\", \"6\", \"4\")" "c(\"9\", \"6\", \"8\", \"8\", \"9\", \"6\", \"10\", \"4\", \"6\", \"4\")" ...
  ..$ V3 : chr [1:10] "c(\"2\", \"2\", \"9\", \"1\", \"5\", \"10\", \"4\", \"3\", \"5\", \"8\")" "c(\"9\", \"10\", \"4\", \"2\", \"10\", \"8\", \"8\", \"8\", \"2\", \"7\")" "c(\"9\", \"6\", \"9\", \"8\", \"2\", \"3\", \"NA\", \"10\", \"6\", \"4\")" "c(\"9\", \"6\", \"8\", \"8\", \"9\", \"6\", \"10\", \"4\", \"6\", \"4\")" ...
  ..$ V4 : chr [1:10] "c(\"2\", \"2\", \"9\", \"1\", \"5\", \"10\", \"4\", \"3\", \"5\

So basically I'm stuck and I don't know what else I can do so any advice will be much appreciated.

Alejandro Carrera
  • 513
  • 1
  • 4
  • 14
  • They already are character, you can check: `sapply(A, class)` – Jilber Urbina Aug 02 '21 at 22:42
  • If you want to coerce the columns to character *"in order to rbind them later"*, then don't, you can simply rbind them as long as the columns are not of class `"factor"`. – Rui Barradas Aug 02 '21 at 22:48
  • @JilberUrbina I know but that's a fake dataset. My original data.frames have many flavors: numeric, date, factor, etc. but I need to put them all in one object before any manipulation. – Alejandro Carrera Aug 02 '21 at 23:19
  • 1
    In that case, you should provide a [great reproducible example](https://stackoverflow.com/q/5963269/1315767) – Jilber Urbina Aug 02 '21 at 23:23

2 Answers2

3

You must coerce the columns of each data.frame to character one by one.

lapply(target, function(x) {
  x[] <- lapply(x, as.character)
  x
}) -> target

df <- do.call(rbind, target)
Rui Barradas
  • 70,273
  • 8
  • 34
  • 66
3

With tidyverse you could do

library(purrr)
library(dplyr)

target %>%
   map(~ mutate(., across(everything(), as.character))) %>%
   bind_rows()

to get your final data.frame

   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
1   2  9  9  9 10  8  5  2  2   9
2   2 10  6  6  5  5  6  8  6   1
3   9  4  9  8  8  4 NA  3  2   9
4   1  2  8  8  1  8  5  5  6   1
5   5 10  2  9  4  9  1  8  5   9
6  10  8  3  6  7  3 NA  8  9   5
7   4  8 NA 10  1  5  1  6  4   3
8   3  8 10  4 NA 10  3  2  4  NA
9   5  2  6  6  8  7  4  7  7   5
10  8  7  4  4 10  5  5  8  2   2
11  G  F  B  C  C  J  I  A  I   H
12  B  J  H  F  G  H  C  D  J   C
13  G  I  F  C  B  F  D  H NA   I
14 NA  D  E NA  C  G  F  F  H   F
15  F  E  I  G  C  D NA  F  B   H
16  J  G  H  C  E  A  G  I  I   F
17  F  D  F  H NA  J  G  I  D   I
18  F  F  A  G  I  E  I  G  E   C
19  I  J  B  E  J  H  H  E  J   G
20  E  C  G  J  C  G  G  F  J   H
21  h  i  e  c  a  f  b  b  h   d
22  h NA  a  i  i  c  a  c  f   j
23  d  i NA NA  e  a  a  j  h  NA
24  f  j  d  d  f NA  d  j  c   b
25  e  d  h  d  h NA  h  b  a   a
26  j  f  c  h NA  a  i  f  e   d
27 NA  d  b  g  d NA  e  b  i  NA
28  i  i  h  f  d  a  i  a  h   b
29  i  h NA  h  g  g  i  f  j   h
30 NA  c  a  d  d NA  e  b  f   a
Martin Gal
  • 16,640
  • 5
  • 21
  • 39