使用For循环或Apply改变多个 Dataframe 的多个列

dced5bon  于 2022-12-06  发布在  其他
关注(0)|答案(2)|浏览(183)

对于下一个问题,我尝试使用循环或应用系列解决方案。

df1 <- data.frame(a = c(1,2,3,NA,NA,NA,NA,NA,9,NA),b = c(1,2,3,4,NA,NA,NA,8,9,10),c = c(1,2,3,NA,NA,NA,7,8,NA,NA))

df2 <- data.frame(a = c(1,2,3,4,5,6,NA,NA,NA,10),b = c(1,2,3,4,NA,NA,NA,8,9,10),c = c(1,2,3,NA,NA,NA,7,8,NA,NA))

df5 <- data.frame(a = c(1,2,3,4,5,6,NA,NA,9,10),b = c(1,2,3,4,5,6,NA,8,9,10),c = c(1,2,3,NA,NA,NA,7,8,9,NA))

在这里我尝试使用na.approx来填补一些NA空白。我的想法是:

l <- c(1,2,5)
for (i in l){
    df[[i]] <- df[[i]] %>% mutate(a = na.approx(a, na.rm = FALSE))
    df[[i]] <- df[[i]] %>% mutate(b = na.approx(b, na.rm = FALSE))
    df[[i]] <- df[[i]] %>% mutate(c = na.approx(c, na.rm = FALSE))
}

在本例中,我得到以下错误:

Error in UseMethod("mutate") : 
no applicable method for 'mutate' applied to an object of class "c('double', 'numeric')"

我的实际数据得到这个错误:

Error in `vectbl_as_col_location2()`:
! Can't extract columns past the end.
i Location 13101 doesn't exist.
i There are only 16 columns.

其中“13101”将是名为“df 13101”的 Dataframe 的一部分。
当我检查 Dataframe 的类时,我得到

[1] "data.frame"

但我得到的实际 Dataframe

[1] "grouped_df" "tbl_df"     "tbl"        "data.frame"

当我检查每个变量的类型时,我想改变的都是数字(示例和真实的的)。
我需要了解如何正确地调用这些 Dataframe ,以及由于数据类或mutate的使用而可能面临的问题。我尝试过使用mapply,但我对R非常陌生,几乎不了解整个apply家族。
任何帮助都将是伟大的,感谢阅读!

u5i3ibmn

u5i3ibmn1#

问题中的代码存在以下问题:

  1. df[[1]]df1不同。第一个引用df的第一列(不存在),第二个是有效输入。相反,如果edf1等所处的环境,那么我们可以根据字符串"df1"df1引用为e[["df1"]]
    1.由于na.approx可以一次处理整个数字 Dataframe ,因此没有必要将na.approx分别应用于每一列。
    1.这对您来说可能是个问题,也可能不是,但请注意,代码会覆盖df1等,因此如果您希望在运行后再次测试它,则必须重新创建原始的df1等。您可能希望使用下面第二种方法中所示的列表。
    下面我们假设输入数据框位于全局环境中,即位于您的工作空间中。(如果数据框位于当前环境中,而不是全局环境中,请将e <- ...行替换为e <- environment()。如果数据框仅在函数中定义和定位,并且在同一函数中引用它们,则会出现这种情况。)
    e[[nm]]指的是在e环境中的对象,其名称由nm变量中的字符串的值给出。然后我们将na.approx应用于该对象,并将其赋值回去。注意,当应用于 Dataframe 时,na.approx返回一个矩阵,因此我们使用左手的[]将矩阵中的值插入 Dataframe 。
library(zoo)

e <- .GlobalEnv
nms <- paste0("df", l)
for (nm in nms) e[[nm]][] <- na.approx(e[[nm]], na.rm = FALSE)

或者将数据框放入命名列表L

L <- mget(nms) # nms defined above
for (nm in nms) L[[nm]][] <- na.approx(L[[nm]], na.rm = FALSE)
91zkwejq

91zkwejq2#

如果 Dataframe 存储在列表中,则更容易执行此操作。然后,您可以将函数应用于每个数值列。

library(dplyr)
library(zoo)

l <- c(1,2,5)
list_of_data <- mget(paste0('df', l))

list_of_data <- purrr::map(list_of_data, ~.x %>%
                      mutate(across(where(is.numeric), 
                       ~na.approx(.x, na.rm = FALSE))))

list_of_data
#$df1
#    a  b  c
#1   1  1  1
#2   2  2  2
#3   3  3  3
#4   4  4  4
#5   5  5  5
#6   6  6  6
#7   7  7  7
#8   8  8  8
#9   9  9 NA
#10 NA 10 NA

#$df2
#    a  b  c
#1   1  1  1
#2   2  2  2
#3   3  3  3
#4   4  4  4
#...
#...

如果希望新值再次反映在实际 Dataframe 中,请使用list2env

list2env(list_of_data, .GlobalEnv)

相关问题