4

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

Excel 输出格式

并获取导入以添加行,以便每组四行间隔 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)))

输出按照我想要的方式格式化,但我需要修复endRowand endCol,并且不知道如何......任何建议将不胜感激。

4

3 回答 3

2

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

我正在通过 via阅读,但如果您愿意,您可以从XLconnectreadxl::read_excel的 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:”开头的文件路径信息的行来完成。要找出这些在哪里,请在整个数据集的第一列上使用cumsumwith 。grepl

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)
于 2016-08-29T21:39:17.793 回答
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)
于 2016-08-29T20:05:32.677 回答
0

我知道这是一篇旧帖子,但无论如何我都会添加我的 .02。我认为您应该使用一些简单的 VBA 在 Excel 中组织所有内容,然后将结构良好的文件读入 R。我认为与在 R 中执行所有操作相比,使用 Excel 处理这样的事情要容易得多,因为您可以清楚地看到。您应该始终使用正确的工具来完成工作。

于 2016-10-20T16:28:20.960 回答