如何将一个数据帧逐行拆分为多个数据帧,然后将其导出到Excel? [R

时间:2020-11-05 17:07:46

标签: r dplyr

这是我正在使用的数据

Sales <- data.frame(State  = c("New York", "New Jersey", "Texas","New Mexico","California",
                                "Kansas","Florida","Alaska","Montana", "Maine"),
                     
                  Units = c(455,453,125,135,135,568,451,125,215,314),
                  
                  Sales = c("20000","12530","51110","54110","65000",
                            "58220","54612","45102","45896","12510"),
                             
                  ManagerName = c("Chip","Kelly","Steve","Young","Troy",
                                  "Aikman", "Chad","Pennington","Mike","Vick")
                  
)

我的最终目标是为每个“州”拥有10个不同的excel文件。

我知道我可以做类似的事情

#Seperate by State
library(dplyr)
NewYork <- Sales %>% filter(State == "New York") 

#Save to excel
library(xlsx)
write.xlsx(NewYork, file="NewYork-Sales-November2020.xlsx", 
           sheetName="NewYork")

但是问题是我有50多个行,并且不想让50个命令按状态过滤,然后又不希望有50个命令来写入excel文件。

是否有一种更有效的方法将每一行“状态”保存到不同的excel文件中?

4 个答案:

答案 0 :(得分:1)

以下是问题的要求,我已经用发布的数据对其进行了测试。

  1. <script src="sql.js"></script> <script> var data; config = { locateFile: filename => `sql.js` } </script> <script> initSqlJs(config).then(function (SQL) { var db = new SQL.Database(); db.run(`CREATE TABLE notes ( id integer primary key, /* 0 */ guid text not null, /* 1 */ mid integer not null, /* 2 */ mod integer not null, /* 3 */ usn integer not null, /* 4 */ tags text not null, /* 5 */ flds text not null, /* 6 */ sfld integer not null, /* 7 */ csum integer not null, /* 8 */ flags integer not null, /* 9 */ data text not null /* 10 */ );`) db.run( `INSERT INTO notes (id, guid, mid, mod, usn, tags, flds, sfld, csum, flags, data) VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0, 0, '')`, 123,"abcdef", 12345, 56789, -1, "tags", "hi", 0); }); </script> 中的数据sql.js:89 Uncaught Error: NOT NULL constraint failed: notes.guid at c.handleError (sql.js:89) at a.step (sql.js:80) at c.run (sql.js:86) at <anonymous>:1:5
  2. 创建工作簿;
  3. 将工作表添加到工作簿中;
  4. 将每个子data.frame写入工作簿;
  5. 将所有内容保存到磁盘。

工作表以function stringswords() { const ss=SpreadsheetApp.getActive(); const sh=ss.getSheetByName('Sheet1'); const sr=2; const rgd=sh.getRange(sr,1,sh.getLastRow()-sr+1,2); const data=rgd.getDisplayValues(); const rgw=sh.getRange(sr,3,sh.getLastRow()-sr+1,1); const words=rgw.getDisplayValues().flat(); const wiObj={}; words.forEach(function(w,i){wiObj[w]=i}); const rgr=sh.getRange(sr,4,sh.getLastRow()-sr+1,1); rgr.clearContent(); var results=rgr.getValues(); words.forEach(function(w,i,A){ data.forEach(function(r,j,D) { if(data[j][0] && data[j][0].indexOf(w)!=-1) { results[wiObj[w]][0]+=Utilities.formatString('String:%s Vol:%s\n',data[j][0],data[j][1]); } }); }); rgr.setValues(results); } 命名。

split

comments中所述,如果工作表名称包含太多字符,超过了Excel的31个字符限制,则以下内容将命名工作表StateState等。

library(openxlsx)

sp <- split(Sales, Sales$State)
names(sp) <- ifelse(nchar(names(sp)) > 31, substr(names(sp), 1, 31), names(sp))
wb <- createWorkbook(creator = "FruityPebblePug")
lapply(seq_along(sp), function(i){
  addWorksheet(wb, sheetName = names(sp)[[i]])
})
lapply(seq_along(sp), function(i){
  writeData(wb, sheet = names(sp)[[i]], sp[[i]])
})
saveWorkbook(wb, "Sales-November2020.xlsx")

答案 1 :(得分:0)

简短的for()循环示例

for (i in Sales$State){
  print(i)
  FilterData <- Sales %>% filter(State == i) 
  filename<-paste0(i, "-Sales-Nov2020.xlsx")
  write.xlsx(FilterData, file=filename, sheetName=i)
}

答案 2 :(得分:0)

也许试试这个

ls_of_dfs <- split(Sales, Sales$State)
mapply(write.xlsx, ls_of_dfs, sheetName = names(ls_of_dfs), MoreArgs = list(file = "NewYork-Sales-November2020.xlsx", append = TRUE))

在尝试上面的代码之前,请记住删除工作目录中任何名为“ NewYork-Sales-November2020.xlsx”的文件。您需要从头开始。

答案 3 :(得分:0)

我通常更喜欢将所有文件都写在一个单独的文件中。否则,您可以使用purrr::iwalk()函数将它们每个都写入一个单独的文件中。

library(rlang)
library(tidyverse)
library(writexl)

按组划分并为每个列表命名

# https://github.com/tidyverse/dplyr/issues/4223
named_group_split <- function(.tbl, mysep = "", ...) {
  grouped <- group_by(.tbl, ...)
  names <- rlang::eval_bare(rlang::expr(paste(!!!group_keys(grouped), sep = mysep)))
  
  grouped %>%
    group_split(., .keep = FALSE) %>%
    rlang::set_names(names)
}

Sales_list <- Sales %>% 
  named_group_split(., mysep = "", State)
Sales_list

# make temporary directory
tmp_dir <- tempdir()

将每个列表写到一个文件中的每张纸上

write_xlsx(Sales_list, file.path(tmp_dir, "Sales_by_state_all.xlsx"))

将每个列表写入单独的文件

iwalk(Sales_list, ~ write_xlsx(.x, file.path(tmp_dir, paste0("Sales_", .y, ".xlsx"))))