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

时间:2019-03-04 12:18:19

标签: r loops

我当前正在创建一个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。我已经在问题中提到了这些元素的字符串拆分。

1 个答案:

答案 0 :(得分:1)

由于我无权访问您的数据,因此我将尝试通过示例数据帧和任意操作来回答您的问题,该示例数据框和任意操作代表您可能已在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())

下一行将创建一个列表,其条目为数据框。 可以使用名称(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行中获得有趣的输出,总结分配的数据类型,如果在全局环境中调用这些数据框,则它们现在应与转换后的数据框列表中的条目匹配