专有软件生成丑陋的excel表...我可以将它们放入R吗?

时间:2016-08-29 19:16:04

标签: r excel xlconnect

我们收集蝙蝠呼叫并对其进行分析,输出是一场噩梦。我想简化我们的流程,但我很难过。如何从excel中获取数十个文件,如下所示:

Excel output format

获取导入以添加行,以便每行四行间隔2行(即行3-6,9-12,15-18等 - 每个项目的间距相同)导入直到达到空白空间(每个项目的重复次数不同)?我还想在每个四行段的空白处endCol ...

我可以使用以下方法轻松指定给定网站的范围:

   df<-t(readWorksheetFromFile("file directory",sheet=2,
        header=FALSE,startCol=2,startRow=3,endCol=5,endRow=6))

然后它变得非常难看,但我已经做到了:

    colnames(df)<-c("Species","n","percent","mle")
    BCID.df<-transform(BCID.df,Species=as.character(as.character(Species)),
    n=as.numeric(as.character(n)),percent=as.numeric(as.character(percent)),
               mle=as.numeric(as.character(mle)))

输出的格式符合我的要求,但我需要修复endRowendCol,并且不知道如何......任何建议都会非常受欢迎。

3 个答案:

答案 0 :(得分:2)

我会像评论中提到的@Frank一样解决这个问题。我将整个文件作为一个大文件阅读,然后根据文件路径信息将其拆分为一个列表。将这些数据拆分为列表后,可以在lapply循环中清理每个数据集。

我正在通过readxl::read_excel,但如果您愿意,可以从 XLconnect 中通过via函数读取整个文件。

library(readxl)
orig = read_excel("test.xlsx", col_names = FALSE)

某些假数据的前六行看起来像:

                                                    X0    X1    X2    X3    X4    X5    X6
                                                 <chr> <chr> <chr> <chr> <chr> <chr> <chr>
1 c:\\file directory\\acoustic data\\Site 10\\20160517  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>
2                               identification summary  <NA>  <NA>  <NA>  <NA>  <NA>  <NA>
3                                                   ID  EPFU  LANO  <NA>   MID  <NA>  <NA>
4                                                    N    70    12  <NA>     4  <NA>  <NA>
5                                                    %    16     3  <NA>    13  <NA>  <NA>
6                                               MLE(p)  1E-3  2E-3  <NA>  <NA>  <NA>  <NA>

此原始文件应拆分为单独的表,可以根据包含以“c:”开头的文件路径信息的行来完成。要确定这些位置,请在整个数据集的第一列上使用cumsumgrepl

groups = cumsum(grepl("c:", orig$X0))

使用此向量拆分文件,通过split将每个单独的表保存到列表中。

orig_list = split(orig, groups)

现在剩下的工作是清理每个数据集,转置事物并删除任何额外的行和列。这也是您可以从文件路径中提取站点和日期信息以添加到数据集以保持组织有序的地方,我证明了这一点,但并非绝对必要。我把这一切都放在一个函数中,用于lapply。注意我一度使用readr::type_convert来确保数值变量被正确转换。

clean_data = function(data) {
    # Get rid of any empty headers (missing values in first column)
    new = data[!is.na(data[,1]),]

    # Transpose
    new = t(new)

    # Put into data.frame, removing extraneous columns 1 to 2
            # and using first row as variable names
    # Convert variables to appropriate type at same time using readr::type_convert
    new2 = readr::type_convert(as.data.frame(new[-1, -(1:2)]))
    names(new2) = new[1, -(1:2)]

    # Add site and date columns by pulling info from original "c:\\..." cell
    new2$site = unlist(strsplit(new[1], "\\\\"))[4]
    new2$date = unlist(strsplit(new[1], "\\\\"))[5]

    # Remove everything after first missing ID
    new2[cumsum(is.na(new2$ID)) == 0,]
}

现在循环遍历所有块并清理每个块。生成的已清理文件将位于列表中。如果需要,您可以将这些行绑定到一个数据集中。

lapply(orig_list, clean_data)

答案 1 :(得分:1)

快速又脏,但如果每个块的尺寸相同,这应该有效,如示例暗示的那样:

library(XLConnect)

# Read the whole sheet in once
df <- readWorksheetFromFile("file directory",sheet=2, header=FALSE)

# Figure out how many code chunks you have (each appears to be 7 rows)
nChunks <- floor(nrow(df)/7)

# create blank list where you can house the different chunks
l <- vector("list", length=nChunks)

# Iterate over the chunks reading them each in to their own list element
for(i in 1:nChunks){
  if(i > 1){
  l[[i]] <- t(readWorksheetFromFile("file directory", sheet=2, header=FALSE, startCol=2, startRow=3, endCol=5, endRow=6))
  }
  else{
    l[[i]] <- t(readWorksheetFromFile("file directory", sheet=2, header=FALSE, startCol=2, startRow=3+(7*i), endCol=5, endRow=6+(7*i)))
  }
}

然后你可以进行相同的转换,但是使用lapply来利用列表中的块。

不同的可能列标签使这有点复杂,但是因为你说有一组相对较少的列名,我只想编写一个函数来替换它们,具体取决于初始名称:

renameCols <- function(x){
        # First possible permutation
if(identical(colnames(x),c("nameOfColumn1","nameOfColumn2","nameOfColumn3")) {colnames(x) <- c("newName1","newName2","newName3")}
        # Second possible permutation
if(identical(colnames(x),c("nameOfColumn1","nameOfColumn2","nameOfColumn3")) {colnames(x) <- c("newName1","newName2","newName3")}
# ... etc
return(x)
}

然后将列名替换函数应用于每个块(每个块存储在列表的不同元素中):

lapply(l, renameCols)

答案 2 :(得分:0)

我知道这是一个旧帖子,但无论如何我还要添加.02。我认为你应该使用一些简单的VBA来将所有内容组织在Excel中,然后将一个结构良好的文件读入R中。我认为这样的事情使用Excel更容易,与在R中完成所有工作相比,你可以清楚地看到。你应该总是使用正确的工具来完成工作。