列名称tolower()递归(在数据帧列表中)

时间:2016-04-14 20:27:35

标签: r list recursion lapply

这应该是显而易见的,但我仍然没有考虑lapply及其亲属,我还没有在SO或Google上找到明确而简单的答案。因此,对于noobness道歉,这里有:

我有一个包含多个嵌入的列表,有点像这样(从here中获取可重现的示例):

lst <- structure(list(Df1 = structure(list(Df1 = structure(list(Date = structure(c(14611, 14612), class = "Date"), Ta_200 = c(10.0067787761421, 5.9095282339839 )), .Names = c("Date", "Ta_200"), row.names = c(NA, -2L), class = "data.frame"), Df2 = structure(list(Date = structure(c(14611, 14612), class = "Date"), rH_200 = c(64.9115310510325, 90.8615907551521)), .Names = c("Date", "rH_200"), row.names = c(NA, -2L), class = "data.frame")), .Names = c("Df1", "Df2")), Df2 = structure(list(Df1 = structure(list(Date = structure(c(14642, 14643), class = "Date"), Ta_200 = c(9.91976687351846, 8.79129183854663 )), .Names = c("Date", "Ta_200"), row.names = c(NA, -2L), class = "data.frame"), Df2 = structure(list(Date = structure(c(14642, 14643), class = "Date"), rH_200 = c(76.9297879127307, 75.8021788747459)), .Names = c("Date", "rH_200"), row.names = c(NA, -2L), class = "data.frame")), .Names = c("Df1", "Df2"))), .Names = c("Df1", "Df2"))

目标:使用tolower()将所有级别的所有列名称设为小写,用于深度为2或3级的递归列表(如此处所示)。我可以循环遍历列表元素,但我正在尝试遵循我在任何地方看到的建议,以避免循环并使用来自apply系列和dplyr的内容。

我可以将lapply用于第二级,如下所示:

lapply(lst, function(x) { names(x) <- tolower(names(x)) } )

但是:(1)我不明白如何以递归方式为第1和第2(和第3)级别执行此操作,以及(2)我有点想知道如何将新的小写名称实际写入列表items(上面的行只返回它们)。

3 个答案:

答案 0 :(得分:3)

一个递归调用自身的函数可以解决这个问题 你不反对所有级别的所有名字被退回 小写...

all_to_lower <- function(x) {
    ##  Update the name at the desired level, when present.
    if (! is.null(names(x)))
        names(x) <- tolower(names(x))
    ##  Decide if an iterative step should be used.
    if (is.list(x) & ! is.data.frame(x)) 
        x <- lapply(
            X = x,
            FUN = all_to_lower)
    ##  Return to workflow.
    x
}

all_to_lower(lst)
$df1
$df1$df1
        date    ta_200
1 2010-01-02 10.006779
2 2010-01-03  5.909528

$df1$df2
        date   rh_200
1 2010-01-02 64.91153
2 2010-01-03 90.86159


$df2
$df2$df1
        date   ta_200
1 2010-02-02 9.919767
2 2010-02-03 8.791292

$df2$df2
        date   rh_200
1 2010-02-02 76.92979
2 2010-02-03 75.80218

编辑:当然可以调整功能,以便只影响数据帧的名称。只需将(! is.null(names(x)))替换为(! is.null(names(x)) & is.data.frame(x))

答案 1 :(得分:1)

这是一个针对两级问题的解决方案。它有点密集

# double lapply with as.data.frame wrapping second lapply
noCapsData <- lapply(lst, function(level2) lapply(level2, 
                  function(dfnames) setNames(dfnames, tolower(names(dfnames)))))

此例程检查字符向量,如果data.frames中有多个数据类型,这可能很有用。

答案 2 :(得分:0)

您可以嵌套lapply的{​​{1}},具体取决于列表深度的层数。如果所有data.frame都在一个级别上,那么您可以使用

之类的东西
setNames

如果您有不同级别的data.frames,您可能需要检查您正在迭代的项目是否为data.frames:

lapply(lst, function(x){lapply(x, function(y){setNames(y, tolower(names(y)))})})

如果您的列表更深入,请再次迭代。

确实存在lapply(lst, function(x){if(is.data.frame(x)){ setNames(x, tolower(names(x))) } else { lapply(x, function(y){if(is.data.frame(y)){ setNames(y, tolower(names(y))) }}) }}) rapply的递归版本,但由于data.frames是列表,因此让它在data.frames上正常工作是一件痛苦的事。