基于第二列中的值将值移动到不同的列,XML到data.frame

基于第二列中的值将值移动到不同的列,XML到data.frame,r,xml,R,Xml,tl;dr I在底部有一个简单的问题: 我正在尝试将XML文件转换为R中可使用的表 <toes copyright='(C)version='1.1'> <generated date='2017-01-21 07:45:04'timestamp='1485006304'/> <description> Active TOE vehicle levels and adjustments for the current campaign up t

tl;dr I在底部有一个简单的问题:

我正在尝试将XML文件转换为R中可使用的表

<toes copyright='(C)version='1.1'> <generated date='2017-01-21 
07:45:04'timestamp='1485006304'/>
   <description> Active TOE vehicle levels and adjustments for the current 
   campaign up to the RDP cycle in progress. c0 = the cycle 0 capacity, adj 
   = comma-separated list of cycle:capacity adjustments, cur = current 
   capacity </description>
   <defaults><def att='adj' value=''/></defaults>
       <r toe="deairfor" veh="22" c0="30" cur="30"/>
       <r toe="deairfor" veh="23" c0="40" cur="20" adj="1:35,2:20"/>
       <r toe="deairfor" veh="26" c0="2" cur="2" adj="2:10,3:30"/>
</toes>
我没有导入XML文件的经验,但我认为该文件的格式不正确,因为我没有遇到任何标记中包含数据的XML示例,如。我已经能够通过以下方式提取数据:

library(XML)
source <- "http://wiretap.wwiionline.com/xml/toes.sheet.xml"
xmlfile <- xmlTreeParse(source, useInternalNodes = TRUE)
nodes <- getNodeSet(xmlfile, "/toes//r")
Df1 <- NULL

for(i in 1:length(nodes)) {
Df1 <- t(xmlToList(nodes[[i]]))
Df2 <- smartbind(Df2,Df1[1,])
}
Df2 <- separate(data = Df2, col = adj, into = c("adj1", adj2","adj3"), sep = "\\,")
Df2 <- separate(data = Df2, col = adj1, into = c("adj1","adj1value"), sep = "\\:")
Df2 <- separate(data = Df2, col = adj2, into = c("adj2","adj2value"), sep = "\\:")
Df2 <- separate(data = Df2, col = adj3, into = c("adj3","adj3value"), sep = "\\:")
所以现在的困难在于这个“adj”列。我可以将其与以下内容分开:

library(XML)
source <- "http://wiretap.wwiionline.com/xml/toes.sheet.xml"
xmlfile <- xmlTreeParse(source, useInternalNodes = TRUE)
nodes <- getNodeSet(xmlfile, "/toes//r")
Df1 <- NULL

for(i in 1:length(nodes)) {
Df1 <- t(xmlToList(nodes[[i]]))
Df2 <- smartbind(Df2,Df1[1,])
}
Df2 <- separate(data = Df2, col = adj, into = c("adj1", adj2","adj3"), sep = "\\,")
Df2 <- separate(data = Df2, col = adj1, into = c("adj1","adj1value"), sep = "\\:")
Df2 <- separate(data = Df2, col = adj2, into = c("adj2","adj2value"), sep = "\\:")
Df2 <- separate(data = Df2, col = adj3, into = c("adj3","adj3value"), sep = "\\:")
最后一行需要:(一旦adj1值位于正确的列中,我们也可以删除adj1/adj2/adj3)

我尝试了多种方法将这些单元格向右移动,但经常会出现错误,例如:(adj*列是分隔后的字符,因此为“1”)

应该成为

"TOE" "Veh" "c0" "cur" "adj1" "adj2" "adj3"
deairfor 26 2 2 NA 10 30 

另外一个问题:我觉得我需要使用很多行,因为一开始的XML导入不是很理想,不管怎样,考虑到我的目标,要做得更好?

我会编写一个函数,可以将NAs添加到前缀adj字符串中,然后使用tidyr的
separate

add_NAs <- function(x, n=3){
   y <- strsplit(x, ",")
   sapply( y, function(z){  
      n <- match( 1:n, substr(z,1,1))
      paste(substring(z, 3)[n], collapse=",")
   })
}
add_NAs( c(NA, "1:35,2:20", "2:10,3:30", "1:20,3:5") )
[1] "NA,NA,NA" "35,20,NA" "NA,10,30" "20,NA,5" 

谢谢克里斯的帮助,真的回答了我所有的问题! 下面为感兴趣的任何人显示的最终代码

我只需要先插入一行下载了xml文件的代码,否则它就无法读取它。我用于此的主题:( 此外,对于这个表,我希望在调整后水平“继续”,这是我在末尾对5个类似行所做的。因此,如果c0=10,adj1=20,adj2=NA,那么adj2/Tier2=20

library(XML)
library(tidyr)
add_NAs <- function(x, n=5){
  y <- strsplit(x, ",")
  sapply( y, function(z){  
  n <- match(1:n, substr(z,1,1))
  paste(substring(z, 3)[n], collapse=",")
  })
}

fileURL <- "http://wiretap.wwiionline.com/xml/toes.sheet.xml"
download.file(fileURL, destfile=tf <- tempfile(fileext=".xml"))
doc <- xmlParse(tf)
Test <- XML:::xmlAttrsToDataFrame(doc["//r[@toe]"], stringsAsFactors=FALSE)
Test$adj <- add_NAs(Test$adj)
Test <- separate(data = Test, col = adj, into = c("Tier1","Tier2","Tier3","Tier4","Tier5"), sep = "\\,")
Test$Tier1 <- ifelse(Test$Tier1=="NA",Test$c0,Test$Tier1)
Test$Tier2 <- ifelse(Test$Tier2=="NA",Test$Tier1,Test$Tier2)
Test$Tier3 <- ifelse(Test$Tier3=="NA",Test$Tier2,Test$Tier3)
Test$Tier4 <- ifelse(Test$Tier4=="NA",Test$Tier3,Test$Tier4)
Test$Tier5 <- ifelse(Test$Tier5=="NA",Test$Tier4,Test$Tier5)
库(XML)
图书馆(tidyr)

添加\u NAs试试这篇文章用什么方法从xml创建一个框架,看看它是否适合你。奇怪的是,你发布的xml与url不匹配,因为网页没有adj属性。是的,网页会随着时间的推移而更新。不幸的是,adj只会在两周后再次出现。从不知道
xmlatrstodataframe
方法。将它添加到我的库!是吗正在寻找一种方法。再次检查并找到按钮,谢谢!
"TOE" "Veh" "c0" "cur" "adj"
deairfor 26 2 2 2:10,3:30 
"TOE" "Veh" "c0" "cur" "adj1" "adj2" "adj3"
deairfor 26 2 2 NA 10 30 
add_NAs <- function(x, n=3){
   y <- strsplit(x, ",")
   sapply( y, function(z){  
      n <- match( 1:n, substr(z,1,1))
      paste(substring(z, 3)[n], collapse=",")
   })
}
add_NAs( c(NA, "1:35,2:20", "2:10,3:30", "1:20,3:5") )
[1] "NA,NA,NA" "35,20,NA" "NA,10,30" "20,NA,5" 
x <- XML:::xmlAttrsToDataFrame(doc["//r[@toe]"], stringsAsFactors=FALSE)
x$adj <- add_NAs(x$adj)
separate(x, adj, c("adj1", "adj2", "adj3"), sep="," , convert=TRUE)
       toe veh c0 cur adj1 adj2 adj3
1 deairfor  22 30  30   NA   NA   NA
2 deairfor  23 40  20   35   20   NA
3 deairfor  26  2   2   NA   10   30
library(XML)
library(tidyr)
add_NAs <- function(x, n=5){
  y <- strsplit(x, ",")
  sapply( y, function(z){  
  n <- match(1:n, substr(z,1,1))
  paste(substring(z, 3)[n], collapse=",")
  })
}

fileURL <- "http://wiretap.wwiionline.com/xml/toes.sheet.xml"
download.file(fileURL, destfile=tf <- tempfile(fileext=".xml"))
doc <- xmlParse(tf)
Test <- XML:::xmlAttrsToDataFrame(doc["//r[@toe]"], stringsAsFactors=FALSE)
Test$adj <- add_NAs(Test$adj)
Test <- separate(data = Test, col = adj, into = c("Tier1","Tier2","Tier3","Tier4","Tier5"), sep = "\\,")
Test$Tier1 <- ifelse(Test$Tier1=="NA",Test$c0,Test$Tier1)
Test$Tier2 <- ifelse(Test$Tier2=="NA",Test$Tier1,Test$Tier2)
Test$Tier3 <- ifelse(Test$Tier3=="NA",Test$Tier2,Test$Tier3)
Test$Tier4 <- ifelse(Test$Tier4=="NA",Test$Tier3,Test$Tier4)
Test$Tier5 <- ifelse(Test$Tier5=="NA",Test$Tier4,Test$Tier5)