我收到了数百张包含合并单元格的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
答案 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是由于合并的单元格。
从提议的代码中,cl
和rw
找到合并值的列和行&#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