Home > OS >  Using attribute tables to apply a function between specific elements in lists
Using attribute tables to apply a function between specific elements in lists

Time:03-27

I have two list objects. l1 contains information that has been read in through path files. l2 is a list of values that have similar name components as those in l1. I have assigned attributes to both list based on the names of the elements in the list. I would like to reach my expected results using the attributes that I have assigned to my list.

For example: I would like to apply a function mean() between the elements with the attribute id that are "2013_mean" in l1 to those with the attribute year that are also "2013" in l2. I would like to do the similar thing with those when the attribute for year is "2016".

# File List
l1 <- list(2,3,4,5)
names(l1) <- c("C:/Users/2013_mean.csv",
               "C:/Users/2013_median.csv",
               "C:/Users/2016_mean.csv",
               "C:/Users/2016_median.csv")

attributes(l1) <- data.frame(id = sub("\\.csv", "", basename(names(l1))),
                             year = trimws(basename(names(l1)), whitespace = "_.*"))

# Other List
l2 <- list(8,9,10,15,1)
names(l2) <- c("2013_A",
               "2013_B",
               "2013_C",
               "2016_D",
               "2016_E")

attributes(l2) <- data.frame(year =  trimws(names(l2), whitespace = "_.*"))


expected <- list(mean(c(l1[[1]], l2[[1]])),
                 mean(c(l1[[1]], l2[[2]])),
                 mean(c(l1[[1]], l2[[3]])),
                 mean(c(l1[[3]], l2[[4]])),
                 mean(c(l1[[3]], l2[[5]]))
)

CodePudding user response:

We may use the attributes to split and match and get the mean

i1 <- grepl("mean", attr(l1, "id"))
l1new <- l1[i1]
attr(l1new, "year") <- attr(l1, "year")[i1]
out <- do.call(c, Map(function(x, y) lapply(x, function(z)
      mean(c(z, y))), split(l2, attr(l2, 'year')), l1new))
names(out) <- NULL

-checking with OP's expected

> identical(out, expected)
[1] TRUE

Or another option is to convert the list with attributes to a data.frame, do a merge and use rowMeans and then convert to list with as.list

as.list(rowMeans(merge(transform(data.frame(attributes(l2)),
   l2 = unlist(l2)), 
   subset(transform(data.frame(attributes(l1)), l1 = unlist(l1)), 
   grepl("mean", id), select = c(year, l1)), all.x = TRUE)[-1]))

-output

[[1]]
[1] 5

[[2]]
[1] 5.5

[[3]]
[1] 6

[[4]]
[1] 9.5

[[5]]
[1] 2.5
  • Related