如何使用R

时间:2016-05-29 12:24:46

标签: r excel

我收到了数百张包含合并单元格的Excel表格。发件人坚持使用Excel并合并单元格 - 我无能为力。我如何使用R读取这些?例如,输入表的问题区域的简化版本可能看起来像这样,其中合并的单元格(B2,B3,C2,C3)包含单词“X”。合并单元格的数量及其在工作表中的位置(以及“X”的值)会在不同工作表之间发生变化,并且同一工作表中可能存在多组合并单元格。这些工作表实际上不是表格格式,它们包含其他空单元格。我已成功遍历所有文件,清理整个混乱,重新整形结果并获得一个整洁的数据集(1张而不是736 Excel工作簿)。问题是,到目前为止,我的解决方案忽略了合并单元格中的信息。

    A   B   C   D
1   a   f   i   l
2   b   X       m
3   c           n
4   d   g   j   o
5   e   h   k   p

如何将Excel工作表读入R,以便结果如下所示,单词“X”

    A   B   C   D
1   a   f   i   l
2   b   X   X   m
3   c   X   X   n
4   d   g   j   o
5   e   h   k   p

5 个答案:

答案 0 :(得分:6)

如果VBA / R混合适合您的目的,这里有一个VBA宏,它将取消合并工作表中的所有单元格,同时用相应的值填充未合并区域中的所有单元格:

Sub UnMerge(ws As Worksheet)
    Dim R As Range, c As Range
    Dim v As Variant
    For Each c In ws.UsedRange
        If c.MergeCells Then
            v = c.Value
            Set R = c.MergeArea
            R.UnMerge
            R.Value = v
        End If
    Next c
End Sub

一个简单的测试,以显示它是如何被调用的:

Sub test()
    UnMerge Sheets(1)
End Sub

UnMerged可用作较大程序的一部分,例如迭代文件夹中的所有.xlsx个文件以及文件中所有包含数据的工作表,将它们全部取消并将它们保存为.csv文件。

开启编辑。本机VBA文件处理有点烦人。如果我需要迭代多个文件,我倾向于使用相关的脚本语言VBScript。我不确定您的虚拟Windows是否可以处理VBScript。我认为是因为VBScript是Windows操作系统的标准部分。如果是这种情况,请查看以下是否有效(在备份文件后为了安全起见)。将代码保存为包含要修改的Excel文件的文件夹中具有.vbs扩展名的简单文本文件。然后,只需单击其图标即可。它将遍历包含每个此类文件中的脚本和取消合并表单1的目录中的所有.xlx.xlsx个文件。我没有广泛测试它并且它没有错误处理,但我在一个包含三个Excel文件的文件夹上测试了它,每个文件包含多个合并区域,并且它在我的Windows机器上按预期运行。我不知道它是否适用于你的Mac:

Option Explicit

Dim fso,fol,f,xl, wb, ws,ext,v,r,c

Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set xl = CreateObject("Excel.Application")
xl.DisplayAlerts = False
xl.ScreenUpdating = False
set fol = fso.GetFolder(fso.GetParentFolderName(WScript.ScriptFullName))

For Each f In fol.Files
    ext = LCase(fso.GetExtensionName(f.Name))
    If ext = "xls" Or ext = "xlsx" Then
        Set wb = xl.Workbooks.Open(f.Path)
        Set ws = wb.Sheets(1)
        For Each c In ws.UsedRange
            If c.MergeCells Then
                v = c.Value
                Set R = c.MergeArea
                R.UnMerge
                R.Value = v
            End If
        Next
        wb.Save
        wb.Close   
    End If
Next

答案 1 :(得分:2)

此解决方案假设电子表格中只有一个合并区域,并且唯一缺失的值(NAs)是由合并的单元格引起的。

<强>代码:

library("openxlsx")
data = read.xlsx(xlsxFile = "Book1.xlsx", colNames = F)

cl = min(ceiling(which(is.na(data))/dim(data)[1]))
rw = min(which(is.na(data))%%dim(data)[1])

data[is.na(data)] = data[rw,cl]

示例:

从包含合并单元格的Excel中读取数据:

   X1   X2   X3   X4  X5
1   1    a    q    a  11
2   2    b    w    s  22
3   3    c    e    d  33
4   4    d <NA> <NA>  44
5   5 <NA> <NA> <NA>  55
6   6 <NA> <NA> <NA>  66
7   7    g    u    j  77
8   8    h    i    k  88
9   9    i    o    l  99
10 10    j    p    m 110

如你所见,&#34; d&#34;被合并在第4到6行和第2到第4列。 唯一的NA是由于合并的单元格。

从提议的代码中,clrw找到合并值的列和行&#34; d&#34;。

最后一行找到所有NAs并用&#34; d&#34;。

替换它们

<强>结果:

   X1 X2 X3 X4  X5
1   1  a  q  a  11
2   2  b  w  s  22
3   3  c  e  d  33
4   4  d  d  d  44
5   5  d  d  d  55
6   6  d  d  d  66
7   7  g  u  j  77
8   8  h  i  k  88
9   9  i  o  l  99
10 10  j  p  m 110

注意: 如果您的Excel数据具有列名,则应删除colnames = F

答案 2 :(得分:2)

library(openxlsx)

> data = read.xlsx(xlsxFile = "Your path", fillMergedCells = TRUE,colNames = FALSE)
  

fillMergedCells = TRUE

尝试一下!

答案 3 :(得分:1)

如果你需要做的就是用X填充空单元格,将数据从Excell导出为制表符分隔的文本文件,将它们作为字符(R)导入as.is = TRUE并替换带有X的空白。示例中的最后一行将所有字符列转换为Roland's answer的因子,这对于分析更为方便。

tab <- read.table("yourExcelAsText.txt", sep="\t", header=TRUE, as.is=TRUE)
tab[tab==""] <- "X"
tab <- as.data.frame(unclass(tab))

答案 4 :(得分:0)

你需要通过案例解决。下面的代码解决了你引用的案例。我又补充了一个。将文件另存为csv或读为xlxs。这使用了for,但它可以很容易地进行矢量化。

da=read.table("testtemp.csv",sep=";",na.strings=c("", "NA"),stringsAsFactors = F) 
#str(da)

#add more cases
da[5,1]<-da[5,2]<-da[4,2]<-NA
da

> da
    V1   V2   V3 V4
1    q    f    i  l
2    b    x <NA>  m
3    c <NA> <NA>  n
4    d <NA>    j  o
5 <NA> <NA>    k  p

#function to find cases
cencell=function(da){ #i=2;j=2
  fc=data.frame(matrix(NA,nrow(da)-1,3))
  ij=1
  for (i in 1:(ncol(da)-1))
    for (j in 1:(nrow(da)-1)){
      cst=c(da[j,i+1],da[j+1,i+1],da[j+1,i])
      if(all(is.na(cst))){fc[ij,1:2]<-c(j,i)
      fc[ij,3]<-da[j,i]
      ij<-1+ij}
    }
  fc[1:(ij-1),]
}
(ctc=cencell(da))
#replace cases
daf=da  #i=1
for(i in 1:nrow(ctc)){daf[ctc[i,1]+1,ctc[i,2]]<-ctc[i,3]
daf[ctc[i,1]:(ctc[i,1]+1),ctc[i,2]+1]<-ctc[i,3]
}
daf

> daf
  V1 V2 V3 V4
1  q  f  i  l
2  b  x  x  m
3  c  x  x  n
4  d  d  j  o
5  d  d  k  p