Reputation: 89
I have a list of 59 data frames that I want to merge together. Unfortunately, because I have scraped many of them, the columns in the data frames have different classes. They all have the column "Name", some in factor form and some in character form. I want to change all of them to character form. I tried the following
dts <- c("Alabama","Alaska","Arizona","Arkansas","California","Colorado","Connecticut","Delaware","Florida",
"Georgia","Hawaii","Idaho","Illinois","Indiana","Iowa","Kansas","Kentucky","Louisiana","Maine",
"Maryland","Massachusetts","Michigan","Minnesota","Mississippi","Missouri","Montana","Nebraska",
"Nevada","New_Hampshire","New_Jersey","New_Mexico","New_York","North_Carolina","North_Dakota",
"Ohio","Oklahoma","Oregon","Pennsylvania","Rhode_Island","South_Carolina","South_Dakota","Tennessee",
"Texas","Utah","Vermont","Virginia","Washington","West_Virginia","Wisconsin","Wyoming","Federal",
"CCJail","DC","LAJail","NOLA","NYCJail","OCJail","PhilJail","TXJail")
for(i in 1:length(dts)){
dts[i]$Name <- as.character(dts[i]$Name)
}
but it only gave me the error "Error: $ operator is invalid for atomic vectors". Does anyone know of a good work-around? Thanks in advance for the help!
My ultimate goal is to run
dta <-dplyr::bind_rows(Alabama,Alaska,Arizona,Arkansas,California,Colorado,Connecticut,Delaware,Florida,
Georgia,Hawaii,Idaho,Illinois,Indiana,Iowa,Kansas,Kentucky,Louisiana,Maine,
Maryland,Massachusetts,Michigan,Minnesota,Mississippi,Missouri,Montana,Nebraska,
Nevada,New_Hampshire,New_Jersey,New_Mexico,New_York,North_Carolina,North_Dakota,
Ohio,Oklahoma,Oregon,Pennsylvania,Rhode_Island,South_Carolina,South_Dakota,Tennessee,
Texas,Utah,Vermont,Virginia,Washington,West_Virginia,Wisconsin,Wyoming,Federal,CCJail,
DC,LAJail,NOLA,NYCJail,OCJail,PhilJail,TXJail)
But I get the error "Error: Can't combine ..1$Residents.Confirmed
and ..2$Residents.Confirmed
." There are a ton of columns in each data frame, and they are different classes very often. if anyone has a more elegant solution, I would also be open to that instead! Thanks!
Upvotes: 2
Views: 700
Reputation: 5788
Base R solution:
type.convert(do.call("rbind",
Map(function(x){data.frame(lapply(x, as.character))}, dataframes_list)))
Data thanks @chase171:
d1 <- data.frame(
Name = as.factor(c("name1", "name2")),
Residents.Confirmed = c(0,1)
)
d2 <- data.frame(
Name = c("name3", "name4"),
Residents.Confirmed = c(2,3)
)
dataframes_list <- list(d1, d2)
Upvotes: -1
Reputation: 886998
We can get the datasets loaded into a list
with mget
(assuming the dataset objects are already created in the global environment) and then loop over the list
with map
, change the class
of 'Name' column in mutate
and row bind with suffix _dfr
in map
library(dplyr)
library(purrr)
out <- map_dfr(mget(dts), ~ .x %>%
mutate(Name = as.character(Name)))
If there are many columns that are different class
. May be, it is better to convert to a single class for all the columns and then bind
out <- map_dfr(mget(dts), ~ .x %>%
mutate(across(everything(), as.character)))
out <- type.convert(out, as.is = TRUE)
If the dplyr
version is < 1.0.0
, use mutate_all
out <- map_dfr(mget(dts), ~ .x %>%
mutate_all(as.character))
Upvotes: 2
Reputation: 51
d1 <- data.frame(
Name = as.factor(c("name1", "name2")),
Residents.Confirmed = c(0,1)
)
d2 <- data.frame(
Name = c("name3", "name4"),
Residents.Confirmed = c(2,3)
)
dataframes_list <- list(d1, d2)
for(i in 1:length(dataframes_list)){
dataframes_list[[i]]$Name <- as.character(dataframes_list[[i]]$Name)
}
bind_rows(dataframes_list)
Upvotes: 1