【问题标题】:R lapply function across a list of data frames跨数据帧列表的 R lapply 函数
【发布时间】:2020-09-11 15:01:05
【问题描述】:

这个问题在论坛上有类似的解决方案;但是我无法让代码正常工作,需要提出一个新问题。

我有大约 20 个非常宽的 csv 文件导入到全局环境中。我需要能够删除特殊字符并更改从 CSV 中提取的列的名称。

这是两个数据帧的示例代码,然后生成一个列表:

df1 <- data.frame("ï.ID" = 1, "Q.1" = 2, Q1.1 = 3)
df2 <- data.frame("ï.ID." = 2, "Q.1a" = 3, Q1.1 = 4)
Qs  <- data.frame("Original.Question" = "Q1a", "Question" = "Q.1")

dflist <- lapply(ls(), function(x) if (class(get(x)) == "data.frame") get(x))

当我导入文件时,在 ID 列前面有一个 BOM 字符 i,上面有两个点。我在单个数据帧中使用以下代码,因为我尝试在 dflist 上使用 lappy 都失败了。

names(df1) <- gsub("[^A-Za-z0-9]", "", names(df1))

我想做的第二件事是重命名 csv 中的列。同样,我似乎没有正确的功能来工作。我要修改以循环遍历所有数据帧的具体代码是:

names(df1)[names(df1) 
          %in% Qs$Original.Question] = Qs$Question[match(names(df1)[names(df1) 
          %in% Qs$Original.Question], Qs$Original.Question)]

这允许我使用 CSV 重命名所有问题列,因为在将数据框合并到单个数据框之前必须重命名它们。同样,我似乎无法正确应用 lapply 功能。

对于需要再次提出类似问题,我深表歉意。我尝试过修改代码,但失败得很惨。

【问题讨论】:

  • 特别是当框架具有非常相似的结构和/或意图时,最好将它们存储在最初的list 中,而不是将它们存储在单独的框架中。将它们分开的唯一时间是仅将函数应用于其中一个(有选择地)是常态,而将函数应用于所有它们是极端例外。

标签: r dataframe lapply gsub


【解决方案1】:

您首先需要过滤掉NULL 对象。你可以这样做:

dflist <- Filter(Negate(is.null), dflist)
lapply(dflist, function(x) setNames(x,gsub("[^A-Za-z0-9]", "", names(x))))
[[1]]
   sex  school daysmissed
1    M   north          5
2    F   north          1
3    M central          2
4    M   south          0
5    F   south          7
6    F   south          1
7    F central          3
8    M   north          2
9    M   north          4
10   F   south         15

[[2]]
  ID Q1 Q11
1  1  2   3

[[3]]
  ID Q1a Q11
1  2   3   4

[[4]]
  OriginalQuestion Question
1              Q1a      Q.1

【讨论】:

  • 感谢@Onyambu 两个代码都有效。无论如何将其应用于全球环境中的数据框?或者我可以重命名数据框列表中的问题,然后将它们合并为一个?
  • @Keelin 你应该查看eapply 而不是lapply 或者干脆使用list2env
【解决方案2】:

您可以根据其名称中的模式获取数据框。在示例中,您有df1df2,您可以使用'df' 后跟数字的模式获取列表中的所有数据帧。使用mget 将它们放入列表中,lapply 覆盖它们并重命名列。

list_df <- mget(ls(pattern = 'df\\d+'))
dflist <- lapply(list_df, function(x) 
                 {names(x) <- gsub("[^A-Za-z0-9]", "", names(x));x})

您也可能对R's read.csv prepending 1st column name with junk text 感兴趣,它可以避免在第一列中获取 BOM 字符。

【讨论】:

  • 我所有的文件都是不同的名称,基于年份和时间段的串联,所以我不能根据名称拉取。出现错误:&gt; df1 &lt;- data.frame("ï.ID" = 1, "Q.1" = 2, Q1.1 = 3) &gt; df2 &lt;- data.frame("ï.ID." = 2, "Q.1a" = 3, Q1.1 = 4) &gt; Qs &lt;- data.frame("Original.Question" = "Q1a", "Question" = "Q.1") &gt; &gt; dflist &lt;- lapply(ls(), function(x) if (class(get(x)) == "data.frame") get(x)) &gt; &gt; dflist &lt;- lapply(dflist, function(x) + {names(x) &lt;- gsub("[^A-Za-z0-9]", "", names(x));x}) Error in names(x) &lt;- gsub("[^A-Za-z0-9]", "", names(x)) : attempt to set an attribute on NULL
  • 在我的回答中我没有使用dflist &lt;- lapply(ls(), function(x) if (class(get(x)) == "data.frame") get(x))
  • 我知道是的,虽然真正的文件不是用 df 命名的,但所有文件都是用年份、时间段和类型的串联命名的。所有这些都没有一个模式。
  • 那么他们叫什么名字呢?无论如何,您可以在使用dflist &lt;- lapply(ls(), function(x) if (class(get(x)) == "data.frame") get(x)) 删除NULL 值之后使用dflist &lt;- Filter(length, dflist)
  • 感谢@Ronak 它的工作。我似乎无法在同一条评论中同时标记你和 Onyambu。但是我应该只应用列表中的更改还是全局环境中的所有 df ?然后我需要对问题应用 lapply 函数。非常感谢您的宝贵时间。
猜你喜欢
  • 2019-07-08
  • 2020-05-21
  • 2020-04-04
  • 2020-02-18
  • 1970-01-01
  • 2015-10-12
  • 2023-03-29
  • 2018-06-08
相关资源
最近更新 更多