8

我有一组具有相同列标题的数据框,除了一些列名是大写的而一些是小写的。我想将所有列名转换为小写,这样我就可以制作一个包含所有内容的大数据框。

我似乎无法colnames()在任何循环中工作或应用我写的东西。和:

#create dfs
df1<-data.frame("A" = 1:10, "B" = 2:11)
df2<-data.frame("a" = 3:12, "b" = 4:13)
df3<-data.frame("a" = 5:14, "b" = 6:15)
#I have many more dfs in my actual data

#make list of dfs, define lowercasing function, apply across df list
dfs<-ls(pattern = "df")
lowercols<-function(df){colnames(get(df))<-tolower(colnames(get(df)))}
lapply(dfs, lowercols)

我收到以下错误:

Error in colnames(get(df)) <- tolower(colnames(get(df))) : 
  could not find function "get<-"

如何将所有数据框更改为小写列名?

4

3 回答 3

11

以下应该有效:

dfList <- lapply(lapply(dfs,get),function(x) {colnames(x) <- tolower(colnames(x));x})

像这样的问题通常源于您没有将所有数据帧放在一个数据结构中,然后被迫使用一些尴尬的东西,比如get.

并不是在我的代码中,我首先lapply使用并get实际创建一个数据框列表,然后更改它们的列名。

您还应该知道,您的 lowercols 函数与 R 类似。R 函数通常不会以不返回任何内容但有副作用的方式调用。如果您尝试以这种方式编写函数(这是可能的),您可能会让您的生活变得困难并遇到范围问题。请注意,在我的第二个中,lapply我明确返回了修改后的数据框。

于 2012-04-15T22:18:56.497 回答
4

@joran 的回答在风格和“你可能想以不同的方式做这件事”的信息上都与我的回答有很大的重叠。然而,本着“给人一条鱼,你喂他一天;给他一根锋利的棍子,他可以戳自己的眼睛”……

这是一个以(您认为)您想要的方式执行您想要的功能的功能:

dfnames <- ls(pattern = "df[0-9]+")  ## avoid 'dfnames' itself
lowercolnames <- function(df) {
    x <- get(df)
    colnames(x) <- tolower(colnames(x))
    ## normally I would use parent.frame(), but here we
    ##  have to go back TWO frames if this is used within lapply()
    assign(df,x,sys.frame(-2))
    ## OR (maybe simpler)
    ## assign(df,x,envir=.GlobalEnv)

    NULL
}

以下是两个小写列名并返回结果的替代函数:

lowerCN2 <- function(x) {
    colnames(x) <- tolower(colnames(x))
    x
}

为了完整起见,我将plyr::rename这里包括在内,尽管在这种情况下,它实际上比它的价值更麻烦。

lowerCN3 <- function(x) {
    plyr::rename(x,structure(tolower(colnames(x)),
                             names=colnames(x)))
}

dflist <- lapply(dfnames,get)
dflist <- lapply(dflist,lowerCN2)
dflist <- lapply(dflist,lowerCN3)
于 2012-04-15T22:31:47.923 回答
1

这并不能直接回答您的问题,但可能会解决您要解决的问题;您可以通过以下方式合并不同名称的 data.frames:

df1 <- data.frame("A" = 1:10, "B" = 2:11, x=letters[1:10])
df2 <- data.frame("a" = 3:12, "b" = 4:13, y=LETTERS[1:10])
merge(df1, df2, by.x=c("A","B"), by.y=c("a","b"), all=TRUE)
于 2012-04-16T01:19:22.063 回答