Connor Murray
Connor Murray

Reputation: 313

Problems with binding columns from two data frames using a for loop in R

I have 7 of two different asc files loaded into R, asc[i] and wasc[i], [i] denotes that there are 1:7 ascs and wascs loaded into R. I need to combine the wasc[i] with the asc[i][[1]] (Just the first column in asc[i] with the whole wasc[i] file).

This should be repeated for every pair of asc and wasc files.

The code keeps giving me blank data frames, so I don't know why this doesn't work. The naming is correct, yet the code is not recognizing that the asc[i] and wasc[i] correlate with previously loaded files.

Any help will be greatly appreciated.

# These data frames will reproduce my issue 

asc1 <- data.frame(x= c(rep("A.tif", 20)), y = 1:20)
wasc1 <- data.frame(x= c(rep("B.tif", 20)), y = c(rep("Imager",20)))

asc2 <- data.frame(x= c(rep("A.tif", 20)), y = 1:20)
wasc2 <- data.frame(x= c(rep("B.tif", 20)), y = c(rep("Imager",20)))

asc3 <- data.frame(x= c(rep("A.tif", 20)), y = 1:20)
wasc3 <- data.frame(x= c(rep("B.tif", 20)), y = c(rep("Imager",20)))


for (i in 1:3) {
      d <- paste("asc", i, sep ="")
      f <- paste("wasc", i, sep ="")
      full_wing <- as.character(paste("full_wing", i, sep = ""))
      assign(full_wing,cbind(d[[1]], f))
    }

# Output of full_wing1 data frame

dput(full_wing1)

structure(c("asc1", "wasc1"), .Dim = 1:2, .Dimnames = list(NULL, 
c("", "f")))

Additional Information:

  1. asc files are 19 columns long
  2. wasc files are 13 columns long

I only want to combine column 1 from the asc file with the entire wasc file, thus cutting out the remaining 18 columns of the asc file.

Upvotes: 1

Views: 80

Answers (1)

Gregor Thomas
Gregor Thomas

Reputation: 145765

# put data in a list
asc = mget(ls(pattern = "^asc"))
wasc = mget(ls(pattern = "^wasc"))

full_wing = Map(f = function(w, a) cbind(w, a[[1]]), w = wasc, a = asc)

Map is a nice shortcut for iterating in parallel over multiple arguments. It returns a nice list. You can access the individual elements with, e.g., full_wing[[1]], full_wing[[3]], etc. Map is just a shortcut, the above code is basically equivalent to the for loop below:

results = list()
for (i in seq_along(asc)) {
    results[[i]] = cbind(wasc[[i]], asc[[i]][[1]])
}

I use mget to put the data in a list because in your example you already have objects like asc1, asc2, etc. A much better way to go is to never create those variables in the first place, instead read the files directly into a list, something like this:

asc_paths = list.files(pattern = "^asc")
asc = lapply(asc_paths, read.table)

You can see a lot more explanation of this at How to make a list of data frames?

If you only ever need one column of the asc files, another way to simplify this would be to only read in the needed column, see Only read limited number of columns for some recommendations there.

Upvotes: 1

Related Questions