2017-02-05 51 views
1

我很难将XML文件作为数据框获取到R中。我所使用的数据可以从美国证券交易委员会免费下载,可以找到HEREXML到数据框 - R

第一个可下载选项SEC Investment Advisor Report (37 MB)是我将用作示例的一个。我下载文件后,使用以下代码将其解压缩到我的终端(mac)中:gunzip -d IA_FIRM_SEC_Feed_02_05_2017.xml.gz。这解压到XML格式。从这里开始,我一直在努力把它变成一个R数据框。我已经尝试了使用XML包的不同代码变体,但只能在数据框中获得一个变量或两个变量。这是什么样的数据看,当我打开XML文件等的例子:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<IAPDFirmSECReport GenOn="2017-02-05"> 
<Firms> 
<Firm> 
<Info SECRgnCD="DRO" FirmCrdNb="116085" SECNb="801-63010" BusNm="JACOBSEN CAPITAL MANAGEMENT" LegalNm="JACOBSEN CAPITAL MANAGEMENT, LLC"/> 
<MainAddr Strt1="280 S 400 W" Strt2="SUITE 220" City="SALT LAKE CITY" State="UT" Cntry="United States" PostlCd="84101" PhNb="801.746.7171" FaxNb="801.363.5886"/> 
<MailingAddr/> 
<Rgstn FirmType="Registered" St="APPROVED" Dt="2004-04-07"/> 
<NoticeFiled> 
<States RgltrCd="AZ" St="FILED" Dt="2009-12-10"/> 
<States RgltrCd="UT" St="FILED" Dt="2009-12-10"/> 
</NoticeFiled> 
<Filing Dt="2016-11-09" FormVrsn="10/2012"/> 
<FormInfo> 
<Part1A> 
<Item1 Q1I="Y" Q1M="N" Q1N="N" Q1O="N"> 
<WebAddrs> 
<WebAddr>HTTP://WWW.JACOBSENCAPITAL.COM</WebAddr> 
</WebAddrs> 
</Item1> 
<Item2A Q2A1="Y" Q2A2="N" Q2A3="N" Q2A4="N" Q2A5="N" Q2A6="N" Q2A7="N" Q2A8="N" Q2A9="N" Q2A10="N" Q2A11="N" Q2A12="N" Q2A13="N"/> 
<Item2B/> 
<Item3A OrgFormNm="Limited Liability Company"/> 
<Item3B Q3B="NOVEMBER"/> 
<Item3C StateCD="UT" CntryNm="United States"/> 
<Item5A TtlEmp="4"/> 
<Item5B Q5B1="2" Q5B2="0" Q5B3="4" Q5B4="0" Q5B5="0" Q5B6="0"/> 
<Item5C Q5C1="26-100" Q5C2="0"/> 
<Item5D Q5D1A="Up to 10 percent" Q5D1B="76-99 percent" Q5D1C="0 percent" Q5D1D="0 percent" Q5D1E="0 percent" Q5D1F="0 percent" Q5D1G="Up to 10 percent" Q5D1H="Up to 10 percent" Q5D1I="0 percent" Q5D1J="0 percent" Q5D1K="0 percent" Q5D1L="0 percent" Q5D1M="0 percent" Q5D2A="Up to 25 percent" Q5D2B="More than 75 percent" Q5D2C="0 percent" Q5D2D="0 percent" Q5D2E="0 percent" Q5D2F="0 percent" Q5D2G="Up to 25 percent" Q5D2H="Up to 25 percent" Q5D2I="0 percent" Q5D2J="0 percent" Q5D2K="0 percent" Q5D2L="0 percent" Q5D2M="0 percent"/> 
<Item5E Q5E1="Y" Q5E2="Y" Q5E3="N" Q5E4="Y" Q5E5="N" Q5E6="N" Q5E7="N"/> 
<Item5F Q5F1="Y" Q5F2A="190000000" Q5F2B="0" Q5F2C="190000000" Q5F2D="342" Q5F2E="0" Q5F2F="342"/> 
<Item5G Q5G1="Y" Q5G2="Y" Q5G3="N" Q5G4="N" Q5G5="N" Q5G6="Y" Q5G7="Y" Q5G8="N" Q5G9="N" Q5G10="N" Q5G11="N" Q5G12="N"/> 
<Item5H Q5H="26-50"/> 
<Item5I Q5I1="N" Q5I2="N"/> 
<Item5J Q5J="N"/> 
<Item6A/> 
<Item6B Q6B1="N" Q6B3="N"/> 
<Item7A Q7A1="N" Q7A2="N" Q7A3="N" Q7A4="N" Q7A5="N" Q7A6="N" Q7A7="N" Q7A8="N" Q7A9="N" Q7A10="Y" Q7A11="N" Q7A12="N" Q7A13="N" Q7A14="N" Q7A15="N" Q7A16="N"/> 
<Item7B Q7B="N"/> 
<Item8A Q8A1="N" Q8A2="Y" Q8A3="N"/> 
<Item8B Q8B1="N" Q8B2="N" Q8B3="N"/> 
<Item8C Q8C1="Y" Q8C2="Y" Q8C3="N" Q8C4="N"/> 
<Item8D/> 
<Item8E Q8E="N"/> 
<Item8F/> 
<Item8G Q8G1="N"/> 
<Item8H Q8H="N"/> 
<Item8I Q8I="N"/> 
<Item9A Q9A1A="N" Q9A1B="N"/> 
<Item9B Q9B1A="N" Q9B1B="N"/> 
<Item9C Q9C1="N" Q9C2="N" Q9C3="N" Q9C4="N"/> 
<Item9D Q9D1="N" Q9D2="N"/> 
<Item9E/> 
<Item9F Q9F="1"/> 
<Item10A Q10A="N"/> 
<Item11 Q11="N"/> 
<Item11A Q11A1="N" Q11A2="N"/> 
<Item11B Q11B1="N" Q11B2="N"/> 
<Item11C Q11C1="N" Q11C2="N" Q11C3="N" Q11C4="N" Q11C5="N"/> 
<Item11D Q11D1="N" Q11D2="N" Q11D3="N" Q11D4="N" Q11D5="N"/> 
<Item11E Q11E1="N" Q11E2="N" Q11E3="N" Q11E4="N"/> 
<Item11F Q11F="N"/> 
<Item11G Q11G="N"/> 
<Item11H Q11H1A="N" Q11H1B="N" Q11H1C="N" Q11H2="N"/> 
</Part1A> 
</FormInfo> 
</Firm> 
<Firm> 

它看起来像变量直接上市之前等号和内容(行项目)直接列出的等号后。例如,在该行:<Info SECRgnCD="DRO" FirmCrdNb="116085" SECNb="801-63010" BusNm="JACOBSEN CAPITAL MANAGEMENT" LegalNm="JACOBSEN CAPITAL MANAGEMENT, LLC"/>

我想数据帧如下所示:

SECRgnCD FirmCrdNB SECNb  BusNm 
DRO  116085 801-63010 JACOBSEN CAPITAL MANAGEMENT 

感谢您的帮助。

+0

XML是一种结构化数据格式,具有嵌套的数据结构,在元件和命名空间属性。没有可以将任何XML转换为数据框的灵丹妙药。你想要将哪些元素放入数据框的行中,以及将这些元素的哪些部分用作列? – Spacedman

+0

Duplicate:http://stackoverflow.com/questions/21648980/transform-xml-into-a-data-frame?rq=1 – Spacedman

+0

@ richiepop2,你能告诉我们你的代码尝试吗? –

回答

2

下面的代码应该可以工作;

require(XML) 
data <- xmlParse('./IA_FIRM_SEC_Feed_02_05_2017.xml') 
result <- as.data.frame(t(xmlSApply(data["//Firms/Firm/Info"],xmlAttrs)), 
        stringsAsFactors=FALSE) 
+0

谢谢@Mathew Savage,完美的作品!好奇的是,我如何更改该代码来捕获公司括号之间的所有变量(请参阅上面的更新代码)?这正是我希望代码能够实现的原因,但是我意识到我的描述并不清晰。非常感谢! – richiepop2

1

即使考虑使用XML的内部变量,xmlAttrsToDataFrame()使用三重冒号运算符:

library(XML) 

df <- XML:::xmlAttrsToDataFrame(getNodeSet(doc, path='//Info')) 
# OR df <- XML:::xmlAttrsToDataFrame(doc['//Info']) 

df 
# SECRgnCD FirmCrdNb  SECNb      BusNm       LegalNm 
# 1  DRO 116085 801-63010 JACOBSEN CAPITAL MANAGEMENT JACOBSEN CAPITAL MANAGEMENT, LLC 

每OP的更新来捕获所有属性<Firm>下,在lapply循环使用上面的方法。下面trycatch用于捕获而没有提出警告属性的元素:

# CAPTURE ALL ELEMENT NAMES UNDER <Firm> AND <Part1A> 
firmsnames <- append(xpathSApply(doc, "//Firm/*", xmlName), 
        xpathSApply(doc, "//Part1A/*", xmlName)) 

# ITERATE THROUGH EACH ELEMENT BINDING ATTRS TO DATAFRAME  
dfList <- lapply(firmsnames, function(n) { 
    tryCatch({ 
    return(XML:::xmlAttrsToDataFrame(doc[paste0('//', n)])) 
    }, warning=function(w) return(data.frame(NA))) 
}) 

# FILTER OUT EMPTY DF ELEMENTS IN LIST 
dfList <- Filter(function(i) length(i)>0, dfList) 

# COLUMN BIND ALL LIST ELEMENTS 
df <- do.call(cbind, dfList) 

# RETURNS A DATA FRAME OF 1 ROW AND 182 COLUMNS 
str(df) 
# data.frame': 1 obs. of 182 variables: 
# $ SECRgnCD : Factor w/ 1 level "DRO": 1 
# ..- attr(*, "names")= chr "SECRgnCD" 
# $ FirmCrdNb: Factor w/ 1 level "116085": 1 
# ..- attr(*, "names")= chr "FirmCrdNb" 
# $ SECNb : Factor w/ 1 level "801-63010": 1 
# ..- attr(*, "names")= chr "SECNb" 
# $ BusNm : Factor w/ 1 level "JACOBSEN CAPITAL MANAGEMENT": 1 
# ..- attr(*, "names")= chr "BusNm" 
# $ LegalNm : Factor w/ 1 level "JACOBSEN CAPITAL MANAGEMENT, LLC": 1 
# ..- attr(*, "names")= chr "LegalNm" 
# ... 
+0

谢谢@Parfait!这个解决方案也运行良好。快速提问。当你说:'根据OP的更新捕获下的所有属性,在lapply循环中使用上述方法。“,你能告诉我如何做到这一点的代码?本表中大约有60个变量和约16k个观察值。 – richiepop2

+0

我不理解。这是做这件事的代码。上面的方法意味着'xmlAttrsToDataFrame'。使用您发布的XML运行此解决方案以查看。 – Parfait