0

I have a list of dataframes (these are spatial dataframes) named for example "map_g1_r1_airport", "map_g1_r1_hotel", "map_g1_r2_bank", "map_g1_r2_market"

These are elements that were digitized from several maps. The maps were originally called "map_g1_r1", "map_g1_r2".

I am trying to add a column to each dataframe with the name of the original map using a loop.

Here is what I am trying to do:

map_g1_r1_airport$mapid<-map_g1_r1
With the loop (Unfortunately this does not do what I intend to do. Instead it simply creates a "content" field in the Values board.):
list_df<-c("map_g1_r1_airport", "map_g1_r1_hotel", "map_g1_r2_bank", "map_g1_r2_market")
    for (df in 1:length(list_df)){
      paste(list_df[df],"$mapid<-", 
                    print(content<-gsub("(.*)_.*","\\1", 
                    c(paste(list_df[df]))),sep=""), 
                    quote=FALSE)}

Any help is most welcome!

Here is one example of the data before change:

structure(list(id = c(1, 2, 3), Name = structure(c(1L, 3L, 4L
), .Label = c("A", "B", "C", "D", "E"
), class = "factor"), Year = structure(c(NA_integer_, NA_integer_, 
NA_integer_), .Label = character(0), class = "factor"), geometry = structure(list(
    structure(c(41.4086152370865, 2.44718243982123), class = c("XY", 
    "POINT", "sfg")), structure(c(45.3852740543083, -4.31103098867136
    ), class = c("XY", "POINT", "sfg")), structure(c(38.4200314592624, 
    -6.96113884231683), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT", 
"sfc"), precision = 0, bbox = structure(c(xmin = 41.4086152370865, 
ymin = 2.31103098867136, xmax = 45.4200314592624, ymax = -4.44718243982123
), class = "bbox"), crs = structure(list(epsg = NA_integer_, 
    proj4string = NA_character_), class = "crs"), n_empty = 0L)), sf_column = "geometry", agr = structure(c(id = NA_integer_, 
Name = NA_integer_, Year = NA_integer_), .Label = c("constant", 
"aggregate", "identity"), class = "factor"), row.names = c(NA, 
3L), class = c("sf", "data.frame"))

This is what I would like to get (with the mapid map_g1_r1):

structure(list(id = c(1, 2, 3), Name = structure(c(1L, 3L, 4L
), .Label = c("A", "B", "C", "D", "E"
), class = "factor"), Year = structure(c(NA_integer_, NA_integer_, 
NA_integer_), .Label = character(0), class = "factor"), geometry = structure(list(
    structure(c(41.4086152370865, 2.44718243982123), class = c("XY", 
    "POINT", "sfg")), structure(c(45.3852740543083, -4.31103098867136
    ), class = c("XY", "POINT", "sfg")), structure(c(38.4200314592624, 
    -6.96113884231683), class = c("XY", "POINT", "sfg"))), class = c("sfc_POINT", 
"sfc"), precision = 0, bbox = structure(c(xmin = 41.4086152370865, 
ymin = 2.31103098867136, xmax = 45.4200314592624, ymax = -4.44718243982123
), class = "bbox"), crs = structure(list(epsg = NA_integer_, 
    proj4string = NA_character_), class = "crs"), n_empty = 0L), 
    mapid = c("map_g1_r1", "map_g1_r1", "map_g1_r1")), sf_column = "geometry", agr = structure(c(id = NA_integer_, 
Name = NA_integer_, Year = NA_integer_, mapid = NA_integer_), .Label = c("constant", 
"aggregate", "identity"), class = "factor"), row.names = c(NA, 
3L), class = c("sf", "data.frame"))
3
  • 1
    Could you use dput to give us an example of df? Commented Jan 15, 2021 at 14:29
  • @RonakShah, map_g1_r1_airport has three column (id/city/size) and two rows. map_g1_r2_bank has four column (id/city/size/branch) and only one row. Commented Jan 17, 2021 at 7:20
  • @RonakShah I added the necessary information. Commented Jan 17, 2021 at 14:26

2 Answers 2

2

You can achieve that even without a loop.

I would first start by creating a list with the names you want to see in each spatial data.frame. I assume they are derived from the names of the list.

mapid = names(list_df)

following that you can employ mapply to use a function that takes the first element of a list (or vector) and the first element of another list/vector. Them it moves on and apply the same function to the second elements of each vector. It is essentially a multiple input version of lapply.

The function we will give to mapply is cbind which creates takes takes two data.frames and joins them by column. In this case one data.frame will be your spatial object and the other will be a vector with one single element: the current map name. cbind will naturally convert this name to a 1-column data.frame and repeat the name to match the number of rows in the spatial object.

final = mapply(cbind, list_df, mapid)

I haven't tested it, but it should work.

Sign up to request clarification or add additional context in comments.

1 Comment

Dear @JMenezes, unfortunately I have 44 mapid and 177 list_df. I have not been able to implement your solution even though it looks promising.
1

You can get all the individual dataframes in a list using mget and add a new column with their name using mutate.

Using tidyverse functions you can do this as :

library(dplyr)
library(purrr)

list_df<-c("map_g1_r1_airport", "map_g1_r1_hotel", "map_g1_r2_bank", "map_g1_r2_market")
tmp <- mget(list_df)

result <- imap(tmp, ~.x %>% mutate(map_id = .y))

result will have all changed dataframes in a list, if you want these changes to reflect in the original object you can use list2env.

list2env(result, .GlobalEnv)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.