列名 tolower() 递归地(在数据框列表中)
Column names tolower() recursively (in list of dataframes)
这应该是显而易见的,但我仍然没有想到 lapply
及其亲属,我还没有在 SO 或 Google 上找到一个明确而简单的答案.因此,为菜鸟道歉,这里是:
我有一个包含多个嵌入的列表,有点像这样(从 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 级深度的递归列表(如此处)。我可以遍历列表元素,但我正在尝试遵循随处可见的建议以避免 for 循环并使用 apply
系列和 dplyr
中的内容。
我可以将 lapply
用于第二层,如下所示:
lapply(lst, function(x) { names(x) <- tolower(names(x)) } )
但是:(1) 我不明白如何在第一级和第二级(和第三级)递归执行此操作,并且 (2) 我有点想念如何实际将新的小写名称写入列表项(上面的行只有 returns 它们)。
这是一个两级问题的解决方案。有点密
# 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 中有不止一种数据类型,这可能会有用。
您可以嵌套 lapply
个 setNames
,具体取决于列表的层数。如果所有 data.frames 都在一个级别上,您可以使用
这样的东西
lapply(lst, function(x){lapply(x, function(y){setNames(y, tolower(names(y)))})})
如果您在不同级别上有 data.frames,您可能需要检查您正在迭代的项目是否 data.frames:
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
,lapply
的递归版本,但要让它在 data.frames 上正常工作是一件痛苦的事情,因为 data.frames 是列出。
一个递归调用自身的函数就可以解决这个问题,前提是
您不反对将所有级别的所有名称返回
小写...
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))
.
这应该是显而易见的,但我仍然没有想到 lapply
及其亲属,我还没有在 SO 或 Google 上找到一个明确而简单的答案.因此,为菜鸟道歉,这里是:
我有一个包含多个嵌入的列表,有点像这样(从 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 级深度的递归列表(如此处)。我可以遍历列表元素,但我正在尝试遵循随处可见的建议以避免 for 循环并使用 apply
系列和 dplyr
中的内容。
我可以将 lapply
用于第二层,如下所示:
lapply(lst, function(x) { names(x) <- tolower(names(x)) } )
但是:(1) 我不明白如何在第一级和第二级(和第三级)递归执行此操作,并且 (2) 我有点想念如何实际将新的小写名称写入列表项(上面的行只有 returns 它们)。
这是一个两级问题的解决方案。有点密
# 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 中有不止一种数据类型,这可能会有用。
您可以嵌套 lapply
个 setNames
,具体取决于列表的层数。如果所有 data.frames 都在一个级别上,您可以使用
lapply(lst, function(x){lapply(x, function(y){setNames(y, tolower(names(y)))})})
如果您在不同级别上有 data.frames,您可能需要检查您正在迭代的项目是否 data.frames:
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
,lapply
的递归版本,但要让它在 data.frames 上正常工作是一件痛苦的事情,因为 data.frames 是列出。
一个递归调用自身的函数就可以解决这个问题,前提是 您不反对将所有级别的所有名称返回 小写...
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))
.