繁体   English   中英

R循环根据数据框名称创建多个新列

[英]R loop to create multiple new columns based on dataframe name

我目前正在创建一个R脚本,以从收件箱中提取某些电子邮件附件,将附件放入数据框(与文件名同名)中,然后将数据框名称解析为单个元素,然后可以使用这些元素创建新的数据框中的列。 然后将对它进行rbind处理,最后将其放入SQL表中。

我处于需要循环以遍历数据框名称,解析它们并将其添加为新列的阶段,但是我无法使循环起作用。

我在下面提供了我的代码示例:

df_list <- Filter(function(x) is.data.frame(get(x)), ls())

for(i in df_list){
  i["Filename"]           <- df_list[i]
  i["Campaign_ID"]        <- sapply(strsplit(df_list[i], " "), "[", 1)
  i["Campaign_Name"]      <- str_sub(regmatches(df_list[i], regexpr("(?<=\\ )[^_]+", df_list[i], perl=TRUE)), start = 1, end = str_length(regmatches(df_list[i], regexpr("(?<=\\ )[^_]+", df_list[i], perl=TRUE))) - str_length(regmatches(df_list[i], regexpr("([A-Z]+[A-Z])[^_]+", df_list[i], perl=TRUE)))-1)
  i["Campaign_Code"]      <- regmatches(df_list[i], regexpr("([A-Z]+[A-Z])[^ -]+", df_list[i], perl=TRUE))
  i["Brand"]              <- substr(regmatches(df_list[i], regexpr("([A-Z]+[A-Z])[^ -]+", df_list[i], perl=TRUE)), start = 1, stop = 4)
  i["Campaign_Type"]      <- substr(regmatches(df_list[i], regexpr("([A-Z]+[A-Z])[^ -]+", df_list[i], perl=TRUE)), start = 5, stop = 7)
  i["Campaign_Category"]  <- substr(regmatches(df_list[i], regexpr("([A-Z]+[A-Z])[^ -]+", df_list[i], perl=TRUE)), start = 8, stop = 10)
  i["Campaign_Churn"]     <- substr(regmatches(df_list[i], regexpr("([A-Z]+[A-Z])[^ -]+", df_list[i], perl=TRUE)), start = 11, stop = 13)
  i["Product"]            <- substr(regmatches(df_list[i], regexpr("([A-Z]+[A-Z])[^ -]+", df_list[i], perl=TRUE)), start = 14, stop = 16)
  i["Version"]            <- substr(regmatches(df_list[i], regexpr("([A-Z]+[A-Z])[^ -]+", df_list[i], perl=TRUE)), start = 17, stop = 17)
  i["Segment"]            <- regmatches(df_list[i], regexpr("(?<=\\_)[^ -]+", df_list[i], perl=TRUE))
  i["Churn"]              <- regmatches(df_list[i], regexpr("(?<=\\- )[^ -]+", df_list[i], perl=TRUE))
  i["Stage"]              <- regmatches(df_list[i], regexpr("([S-S]+[a-z]+[a-z]+[a-z]+[a-z] )[^\\s]+", df_list[i], perl=TRUE))
  i["Other"]              <- str_sub(regmatches(df_list[i], regexpr("([S-S]+[a-z]+[a-z]+[a-z]+[a-z] )[^.]+", df_list[i], perl=TRUE)), start = str_length(regmatches(df_list[i], regexpr("([S-S]+[a-z]+[a-z]+[a-z]+[a-z] )[^\\s]+", df_list[i], perl=TRUE)))+2, end = str_length(regmatches(df_list[i], regexpr("([S-S]+[a-z]+[a-z]+[a-z]+[a-z] )[^.]+", df_list[i], perl=TRUE))) - str_length(regmatches(df_list[i], regexpr("\\S+(?=\\.[^.]*$)", df_list[i], perl=TRUE)))-1)
  i["Date"]               <- dmy(regmatches(df_list[i], regexpr("\\S+(?=\\.[^.]*$)", df_list[i], perl=TRUE)))
  print(i)
}

我想这是我在循环中遗漏的简单东西,但似乎无法弄清楚。 我已经尝试过没有解析,只是添加了随机数据,但仍然无法正常工作

为了清楚起见,我还提供了'df_list'的内容(这些确实是数据帧-它们的名称与解析时所使用的文件的名称相同):

[1] "20579 Buzz Testing Nathan 1 BUZZRETJOUCHUALLA_D1A - Churned - Stage 1 Other 28-February-2019.csv"
[2] "20580 Buzz Testing Nathan 2 BUZZRETJOUCHUALLA_D1B - Churned - Stage 1 Other 28-February-2019.csv"
[3] "20581 Buzz Testing Nathan 3 BUZZRETJOUCHUALLA_D1C - Churned - Stage 1 Other 28-February-2019.csv"

编辑:我以为我会添加一些可重现的数据,这应该有助于清理事物。

`20579 Buzz Testing Nathan 1 BUZZRETJOUCHUALLA_D1A - Churned - Stage 1 Other 28-February-2019.csv` <- data.frame(ID = 000000, Code = 'ABCDE')

`20580 Buzz Testing Nathan 2 BUZZRETJOUCHUALLA_D1B - Churned - Stage 1 Other 28-February-2019.csv` <- data.frame(ID = 111111, Code = 'FGHIJ')

`20581 Buzz Testing Nathan 3 BUZZRETJOUCHUALLA_D1C - Churned - Stage 1 Other 28-February-2019.csv` <- data.frame(ID = 222222, Code = 'KLMNO')

然后,在每个数据框中创建一个新列,并使用数据框中名称的元素填充它们。 因此,例如对于第一个数据框,数据框名称的前5位数字将是campaignID。 正如我的问题前面提到的,我已经为这些元素进行了字符串拆分。

由于我无权访问您的数据,因此我将尝试通过示例数据框和任意操作来回答您的问题,该示例数据框和任意操作代表您可能在原始的for循环中指定的列修改过程帖子。 我的解决方案中的结构有些不同。 我没有使用for循环,而是将数据帧组装到列表中,并使用lapply修改了命名列。

df1 <- data.frame(foo = 1:5,
                  bar = c(7, NA, 22, 3, 14),
                  baz = c(T, F, F, NA, T))

df2 <- data.frame(foo = 1:5,
                  bar = c(4, NA, 9, 29, 11),
                  baz = c(T, T, F, NA, T))

df3 <- data.frame(foo = 1:5,
                  bar = c(1, 9, NA, 7, 12),
                  baz = c(F, F, F, NA, F))

dfs <- Filter(function(x) is.data.frame(get(x)), ls())

下一行将创建一个列表,其条目为数据帧。 名称可以使用names(df_list)<-c( 此处为您的名字 )进行更改

df_list <- lapply(dfs, function(x) eval(as.name(x)))

再一次,由于我没有您的原始数据,因此我将任意转换应用于每个数据框的“栏”列,以说明如何将转换集成到此通用解决方案中。 在这里,我只是将“ bar”列中的每个非NA值加1。 希望我不会误解您要实现的目标。 如果不是您需要的更新或注释,或者它不适用于您的特定数据,请发布更新/注释。

df_list <- lapply(1:length(df_list), function(i) {
             reps = dim(df_list[[i]])[[1]]
             df_list[[i]][ ,"bar"] <- df_list[[i]][ ,"bar"] +
               rep(1, times = reps)
             df_list[[i]]
           })

输出应该是一个数据帧列表,其中“ bar”的每个非NA元素都添加了1。 您可以在通过lapply应用的函数中的其他列上添加转换。 如果将数据框放在列表中对您来说不起作用,那么以下代码将在列表中将转换后的数据框分配给全局环境中的原始数据框:

assignment_fun <- function(x, y) {
  assign(x, y, envir = .GlobalEnv)
}

mapply(assignment_fun, dfs, df_list)
df1
df2
df3

您将在控制台的mapply行中看到一个有趣的输出,概述了分配的数据类型,如果在全局环境中调用这些数据框,它们现在应该与转换后的数据框列表中的条目匹配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM