dmvianna
dmvianna

Reputation: 15718

Conditional lapply

So I have a bunch of data frames in a list object. Frames are organised such as

ID     Category    Value
2323   Friend      23.40
3434   Foe         -4.00

And I got them into a list by following this topic. I can also run simple functions on them as shown in this topic.

Now I am trying to run a conditional function with lapply, and I'm running into trouble. In some tables the 'ID' column has a different name (say, 'recnum'), and I need to tell lapply to go through each data frame, check if there is a column named 'recnum', and change its name to 'ID', as in

colnr <- which(names(x) == "recnum"
if (length(colnr > 0)) {names(x)[colnr] <- "ID"}

But I'm running into trouble with local scope and who knows what. Any ideas?

Upvotes: 0

Views: 4726

Answers (2)

mnel
mnel

Reputation: 115382

Use the rename function from plyr; it renames by name, not position:

x <- data.frame(ID = 1:2,z=1:2)
y <- data.frame('recnum' = 1:2,z=3:4)

.list <- list(x,y)
library(plyr)
lapply(.list, rename, replace = c('recnum' = 'ID'))

[[1]]
  ID z
1  1 1
2  2 2

[[2]]
  ID z
1  1 3
2  2 4

Your original code works fine:

foo <- function(x){
  colnr <- which(names(x) == "recnum")

  if (length(colnr > 0)) {names(x)[colnr] <- "ID"}
  x
}
.list <- list(x,y)
lapply(.list, foo)

Not sure what your problem was.

Upvotes: 4

BenBarnes
BenBarnes

Reputation: 19454

If you look at the second part of mnel's answer, you can see that the function foo evaluates x as its last expression. Without that, if you try to change the names of the data.frames in your list directly from within the anonymous function passed to lapply, it will likely not work.

Just as an alternative, you could use gsub and avoid loading an additional package (although plyr is a nice package):

xx <- list(data.frame("recnum" = 1:3, "recnum2" = 1:3),
  data.frame("ID" = 4:6, "hat" = 4:6))

lapply(xx, function(x){ 
  names(x) <- gsub("^recnum$", "ID", names(x))
  return(x)
})
# [[1]]
#   ID recnum2
# 1  1       1
# 2  2       2
# 3  3       3

# [[2]]
#   ID hat
# 1  4   4
# 2  5   5
# 3  6   6

Upvotes: 1

Related Questions