R assign/get 变量作为两个 for 循环中的 df 名称,一个有效,一个无效

R assign/get variables as df names in two for-loops, one works and one doesn't

我正在尝试使用两个 for 循环来

  1. 将一些 csv 文件导入数据框并
  2. 将我自制的函数应用于那些导入的数据框。

我搜索了 assign 和 get 函数,第一步(将 csv 导入 df)有效...

Lines <- c(101, 102, 103, 301, 311, 312, 514, 617, 706, 918)

for (i in 1:length(Lines)) {
assign("dfName", paste0(("df_Line"),Lines[i]))
assign("lineName", paste0(("LineNum_"),Lines[i],(".csv")))
dfName <- read.csv(lineName, encoding="UTF-8")
}

此代码有效并使我 LineNum_101.csv 成为我想要的 df_Line101,从 101 到 918。

所以我继续尝试应用 'function_Merged(df)'(我制作的那个。它在这个问题页的末尾)并且应该使 'df_Line101' 到 'df_101_Merged',从 101 到 918。 但是这个循环有什么问题?

Lines <- c(101, 102, 103, 301, 311, 312, 514, 617, 706, 918)

for (i in 1:length(Lines)) {
assign("dfName", paste0(("df_Line"),Lines[i]))
assign("dfMerged", paste0(("df_"),Lines[i],("_Merged")))
dfMerged <- function_Merged(dfName)
}

它说“错误:$ 运算符对于原子向量无效”。

好吧,我在没有循环的情况下检查了变量本身,并且

assign("dfName", paste0(("df_Line"),Lines[1]))
assign("dfMerged", paste0(("df_"),Lines[1],("_Merged")))
print(dfName)
print(dfMerged)

给了我 [1] 个“df_Line101”和 [1]“df_101_Merged”。

我尝试将我的函数与这两个赋值一起应用。我已经尝试了很多东西,但现在我什么都不知道。

get(dfMerged) <- function_Merged(get(dfName))

给我[找不到函数“get<-”]

get(dfMerged) <- function_Merged(dfName)

game ve [$运算符对原子向量无效]

dfMerged <- function_Merged(get(dfName))

有……是的。它制作了一个名为 dfMerged 的​​全新框架。 function_Merged 虽然有效。

我应该怎么做才能使这个 for 循环起作用? 任何帮助或建议都会非常有用。谢谢!


22/05/24 可复制版本(?idk)

首先是我使用的库(我知道其中很多实际上不会用在这段代码中,但无论如何)

library(ggplot2)
library(dplyr)
library(ggpmisc)
library(plotrix)
library(tidyverse)
library(lubridate)
library(ggrepel)
library(broom)
library(plotly)
library(reprex)
library(readxl)
library(zoo)
library(pracma)

我的工作目录中有大约 100 个 CSV 文件。 文件名格式为“LineNum_(number).csv”

list.files()
'0523_visualize.ipynb''LineNum_101.csv''LineNum_102.csv''LineNum_103.csv''LineNum_104.csv''LineNum_105.csv''LineNum_106.csv''LineNum_107.csv''LineNum_108.csv''LineNum_113.csv''LineNum_114.csv''LineNum_115.csv''LineNum_116.csv''LineNum_117.csv''LineNum_119.csv''LineNum_121.csv''LineNum_201.csv''LineNum_202.csv''LineNum_203.csv''LineNum_211.csv''LineNum_212.csv''LineNum_213.csv''LineNum_216.csv''LineNum_301.csv''LineNum_311.csv''LineNum_312.csv''LineNum_313.csv''LineNum_314.csv''LineNum_315.csv''LineNum_316.csv''LineNum_317.csv''LineNum_318.csv''LineNum_501.csv''LineNum_511.csv''LineNum_512.csv''LineNum_513.csv''LineNum_514.csv''LineNum_601.csv''LineNum_602.csv''LineNum_603.csv''LineNum_604.csv''LineNum_605.csv''LineNum_606.csv''LineNum_607.csv''LineNum_608.csv''LineNum_611.csv''LineNum_612.csv''LineNum_613.csv''LineNum_614.csv''LineNum_615.csv''LineNum_616.csv''LineNum_617.csv''LineNum_618.csv''LineNum_619.csv''LineNum_620.csv''LineNum_622.csv''LineNum_701.csv''LineNum_703.csv''LineNum_704.csv''LineNum_705.csv''LineNum_706.csv''LineNum_711.csv''LineNum_712.csv''LineNum_802.csv''LineNum_911.csv''LineNum_912.csv''LineNum_916.csv''LineNum_918.csv'

每个文件如下所示:

df_Line311 <-read.csv("LineNum_311.csv", encoding = "UTF-8")
head(df_Line311, 5)

A data.frame: 5 × 5
Date    On  Off Transfer    LineNum
<chr>   <int>   <int>   <int>   <int>
1   2020-01-02  15623   12250   3288    311
2   2020-01-03  16598   13078   3410    311
3   2020-01-04  12081   9771    2296    311
4   2020-01-05  9543    7556    1835    311
5   2020-01-06  14779   11607   3321    311
df_Line101 <-read.csv("LineNum_101.csv", encoding = "UTF-8")
head(df_Line101,5)
A data.frame: 5 × 5
Date    On  Off Transfer    LineNum
<chr>   <int>   <int>   <int>   <int>
1   2020-01-02  4250    3725    1061    101
2   2020-01-03  4463    3910    1099    101
3   2020-01-04  3214    2847    753 101
4   2020-01-05  2977    2562    660 101
5   2020-01-06  4197    3673    1041    101

...等等。
这里 On/Off/Transfer 变量是 on/off/transfered 乘坐公交线路 LineNum 的人数。例如在20-01-02,有15623人乘坐了311路公交车。

现在我正在通过三个步骤处理数据:

  1. 仅获取工作日(周二、周三、周四)数据
function_Workdays <- function(dataframe) {
    tempDF <- dataframe
    tempDF$Date <- as.Date(tempDF$Date)
    tempDF$Days <- weekdays(tempDF$Date)
    tempDF$Workdays <- factor(tempDF$Days %in% c("화요일", "수요일", "목요일") )
# 화요일, 수요일, 목요일 means Tue, Wed, Thu each in Korean
    tempDF <- subset(tempDF, Workdays==T)
    return(tempDF)
    rm(tempDF)
}

df_Line311_Workdays <- function_Workdays(df_Line311)
head(df_Line311_Workdays, 5)
A data.frame: 5 × 7
Date    On  Off Transfer    LineNum Days    Workdays
<date>  <int>   <int>   <int>   <int>   <chr>   <fct>
1   2020-01-02  15623   12250   3288    311 목요일 TRUE
6   2020-01-07  14779   11510   3125    311 화요일 TRUE
7   2020-01-08  15571   12315   3433    311 수요일 TRUE
8   2020-01-09  15828   12773   3383    311 목요일 TRUE
13  2020-01-14  15620   12721   3354    311 화요일 TRUE

  1. 将“stats”包中的 运行 媒体函数 (RunMed) 应用于 On 值以进行平滑处理
function_Runmed <- function(dataframe) {
    tempDF <- dataframe
    tempDF$On_RunMed <- runmed(tempDF$On, 7)
    return(tempDF)
    rm(tempDF)
}

df_Line311_Runmed <- function_Runmed(df_Line311_Workdays)
head(df_Line311_Runmed, 5)
    Date    On  Off Transfer    LineNum Days    Workdays    On_RunMed
<date>  <int>   <int>   <int>   <int>   <chr>   <fct>   <dbl>
1   2020-01-02  15623   12250   3288    311 목요일 TRUE    15571
6   2020-01-07  14779   11510   3125    311 화요일 TRUE    15571
7   2020-01-08  15571   12315   3433    311 수요일 TRUE    15571
8   2020-01-09  15828   12773   3383    311 목요일 TRUE    15604
13  2020-01-14  15620   12721   3354    311 화요일 TRUE    15571

  1. 在统计包中也应用 Loess 函数
function_Loess <- function(dataframe) {
    tempDF <- dataframe
    tempDF$NumericDate = as.numeric(tempDF$Date)
    LoessFunction <- 
    stats::loess(On_RunMed ~ NumericDate, data = tempDF, span = 0.1)
    LoessFunction_value <- predict(LoessFunction, se=T)
    Loess_Function_df <- data.frame(LoessFunction_value)
    tempDF$Loess_Fit <- Loess_Function_df$fit
    tempDF$Loess_SE <- Loess_Function_df$se.fit
    return(tempDF)
    rm(tempDF)
}

df_Line311_Runmed_Loess <- function_Loess(df_Line311_Runmed)
head(df_Line311_Runmed_Loess, 5)
A data.frame: 5 × 11
Date    On  Off Transfer    LineNum Days    Workdays    On_RunMed   NumericDate Loess_Fit   Loess_SE
<date>  <int>   <int>   <int>   <int>   <chr>   <fct>   <dbl>   <dbl>   <dbl>   <dbl>
1   2020-01-02  15623   12250   3288    311 목요일 TRUE    15571   18263   15115.58    293.1331
6   2020-01-07  14779   11510   3125    311 화요일 TRUE    15571   18268   15437.50    210.3811
7   2020-01-08  15571   12315   3433    311 수요일 TRUE    15571   18269   15484.75    197.0860
8   2020-01-09  15828   12773   3383    311 목요일 TRUE    15604   18270   15526.54    184.9781
13  2020-01-14  15620   12721   3354    311 화요일 TRUE    15571   18275   15656.93    143.0892

然后我合并了这三个...

function_Merged <- function(dataframe) {  
    df_Workdays <- function_Workdays(dataframe)
    df_Runmed <- function_Runmed(df_Workdays)
    df_Loess <- function_Loess(df_Runmed)
    return(df_Loess)
}

df_311_Merged <- function_Merged(df_Line311)
head(df_311_Merged, 5)
A data.frame: 5 × 11
Date    On  Off Transfer    LineNum Days    Workdays    On_RunMed   NumericDate Loess_Fit   Loess_SE
<date>  <int>   <int>   <int>   <int>   <chr>   <fct>   <dbl>   <dbl>   <dbl>   <dbl>
1   2020-01-02  15623   12250   3288    311 목요일 TRUE    15571   18263   15115.58    293.1331
6   2020-01-07  14779   11510   3125    311 화요일 TRUE    15571   18268   15437.50    210.3811
7   2020-01-08  15571   12315   3433    311 수요일 TRUE    15571   18269   15484.75    197.0860
8   2020-01-09  15828   12773   3383    311 목요일 TRUE    15604   18270   15526.54    184.9781
13  2020-01-14  15620   12721   3354    311 화요일 TRUE    15571   18275   15656.93    143.0892

对于最后一步,我想要数据框中工作目录中的所有这些 csv 文件,并以相同的 df 名称形式应用此合并函数(当然是自动的。这就是让我尝试分配和获取的原因for 循环中的函数)

多亏了我得到的答案,使用数据框列表比那些分配-获取的东西要容易得多。我成功地生成了所有 csv 文件并将我的合并函数应用于它们。

my_list <- c("LineNum_101.csv", "LineNum_102.csv", "LineNum_103.csv")
my_df = lapply(my_list, function(x) read.csv(x, encoding = "UTF-8") )
lapply(my_df, function(x) function_Merged(x))

summary(my_df)
     Length Class      Mode
[1,] 5      data.frame list
[2,] 5      data.frame list
[3,] 5      data.frame list

my_df[1]
A data.frame: 786 × 5
Date    On  Off Transfer    LineNum
<chr>   <int>   <int>   <int>   <int>
2020-01-02  4250    3725    1061    101
2020-01-03  4463    3910    1099    101
2020-01-04  3214    2847    753 101
2020-01-05  2977    2562    660 101
2020-01-06  4197    3673    1041    101

但我需要这些数据帧从列表中退出,以便在应用合并函数后拥有自己的数据帧名称。我怎样才能做到这一点?有什么方法可以使用自动名称导出列表中的每个数据框? (我希望我的列表元素具有名称 df_101_Merged、df_102_Merged、...等等。)嗯...我可以在每个 df 中使用 LineNum 数据吗?

您没有提供可重现的示例,但我将编造一些数据并展示使用列表比 assignget 更好。

## each is just mtcars
my_files = c("mtcars.1.txt", "mtcars.2.txt", "mtcars.3.txt")

我们可以像这样创建一个 list 数据框:

my_list = lapply(my_files, function(x) read.table(x, sep=","))
[[1]]
    V1  V2    V3  V4   V5    V6    V7 V8 V9  V10  V11
1  mpg cyl  disp  hp drat    wt  qsec vs am gear carb
2   21   6   160 110  3.9  2.62 16.46  0  1    4    4
3   21   6   160 110  3.9 2.875 17.02  0  1    4    4
4 22.8   4   108  93 3.85  2.32 18.61  1  1    4    1
5 21.4   6   258 110 3.08 3.215 19.44  1  0    3    1
6 18.7   8   360 175 3.15  3.44 17.02  0  0    3    2
7 18.1   6   225 105 2.76  3.46 20.22  1  0    3    1
8 14.3   8   360 245 3.21  3.57 15.84  0  0    3    4
9 24.4   4 146.7  62 3.69  3.19    20  1  0    4    2
 [ reached 'max' / getOption("max.print") -- omitted 24 rows ]

[[2]]
    V1  V2    V3  V4   V5    V6    V7 V8 V9  V10  V11
1  mpg cyl  disp  hp drat    wt  qsec vs am gear carb
2   21   6   160 110  3.9  2.62 16.46  0  1    4    4
3   21   6   160 110  3.9 2.875 17.02  0  1    4    4
4 22.8   4   108  93 3.85  2.32 18.61  1  1    4    1
5 21.4   6   258 110 3.08 3.215 19.44  1  0    3    1
6 18.7   8   360 175 3.15  3.44 17.02  0  0    3    2
7 18.1   6   225 105 2.76  3.46 20.22  1  0    3    1
8 14.3   8   360 245 3.21  3.57 15.84  0  0    3    4
9 24.4   4 146.7  62 3.69  3.19    20  1  0    4    2
 [ reached 'max' / getOption("max.print") -- omitted 24 rows ]

[[3]]
    V1  V2    V3  V4   V5    V6    V7 V8 V9  V10  V11
1  mpg cyl  disp  hp drat    wt  qsec vs am gear carb
2   21   6   160 110  3.9  2.62 16.46  0  1    4    4
3   21   6   160 110  3.9 2.875 17.02  0  1    4    4
4 22.8   4   108  93 3.85  2.32 18.61  1  1    4    1
5 21.4   6   258 110 3.08 3.215 19.44  1  0    3    1
6 18.7   8   360 175 3.15  3.44 17.02  0  0    3    2
7 18.1   6   225 105 2.76  3.46 20.22  1  0    3    1
8 14.3   8   360 245 3.21  3.57 15.84  0  0    3    4
9 24.4   4 146.7  62 3.69  3.19    20  1  0    4    2
 [ reached 'max' / getOption("max.print") -- omitted 24 rows ]

然后假设我们想要将一个函数应用到所有数据帧——我们可以定义一个函数并使用lapply将它应用到列表中的所有数据帧。在这种情况下,我们只从每个数据框中采样 2 行。

random_function = function(x, n) {
    sample_n(x, n)
}

my_list = lapply(my_list, function(x) random_function(x, n=2))
[[1]]
    V1 V2   V3  V4   V5   V6    V7 V8 V9 V10 V11
1 32.4  4 78.7  66 4.08  2.2 19.47  1  1   4   1
2 15.5  8  318 150 2.76 3.52 16.87  0  0   3   2

[[2]]
    V1 V2  V3  V4   V5   V6    V7 V8 V9 V10 V11
1 10.4  8 472 205 2.93 5.25 17.98  0  0   3   4
2 13.3  8 350 245 3.73 3.84 15.41  0  0   3   4

[[3]]
    V1 V2  V3  V4   V5   V6    V7 V8 V9 V10 V11
1 22.8  4 108  93 3.85 2.32 18.61  1  1   4   1
2 13.3  8 350 245 3.73 3.84 15.41  0  0   3   4

要命名结果列表,我们可以使用 names(),例如:

## obviously change this based on how you want to name the list
library(stringr)
names(my_list) = str_remove_all(my_files, "\.txt")

希望您能根据自己的数据进行调整。