Извлечь часть строки на основе - R - PullRequest
0 голосов
/ 12 июня 2019

HI имеет значение ниже df, и мне нужно извлечь его из числа символов.

Из столбца text1 мне просто нужно число 16593 для идентификатора 1 и 10227 для идентификатора 2.

Желаемые результаты:

    id text1
    1  16593 
    2  10227 

Желаемое число всегда находится в этой строке "no_i</name><primaryKey>true</primaryKey><newValue>16593", поэтому я попытался извлечь число, основанное на 45 символах, из слова no_i, а конец -

Кто-нибудь знает, как я могусделать это?

Пожалуйста, укажите мой df.

 id <- c(1,2)
text1 <- c( 
  "<?xml version=1.0 encoding=UTF-8 standalone=yes?><businessObjectChanges version=1><table><datetime>1556122543608</datetime><name>header</name><row><datetime>1556122543608</datetime><transactionType>UPDATE</transactionType><column><name>status</name><newValue>14</newValue><oldValue>13</oldValue><mimeType>INT</mimeType></column><column><name>no_i</name><primaryKey>true</primaryKey><newValue>16593</newValue><oldValue>16593</oldValue></column></row></table></businessObjectChanges>",
  "<?xml version=1.0 encoding=UTF-8 standalone=yes?><businessObjectChanges version=1><table><datetime>1547028713373</datetime><name>header</name><row><datetime>1547028713373</datetime><transactionType>UPDATE</transactionType><column><name>status</name><newValue>14</newValue><oldValue>13</oldValue><mimeType>INT</mimeType></column><column><name>no_i</name><primaryKey>true</primaryKey><newValue>10227</newValue><oldValue>10227</oldValue></column></row></table></businessObjectChanges>"

)
    my_text <- data.frame (id, text1) 

Ответы [ 4 ]

1 голос
/ 12 июня 2019

вы можете попробовать

my_text$text1 = gsub(".*>(.*)","\\1",my_text$text1)

> my_text
  id text1
1  1 16593
2  2  1022

Регулярное выражение в основном ищет что-либо (.*) до последнего появления > и сохраняет только следующее (которое является вашим числом).
Альтернатива

В качестве альтернативы вы можете использовать

gsub(".*<newValue>(\\d+)<\\/newValue>.*","\\1",my_text$text1)  

Если ваши цифры всегда заключены в <newValue>.

0 голосов
/ 12 июня 2019

У вас есть XML, но вы представили его в поврежденной форме и пытаетесь использовать регулярные выражения вместо запросов «xpath». Восстановите исходный XML, например, с кавычками вокруг версии / кодировки / автономного в первой строке и версии во второй строке, как

txt = '
    '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
     <businessObjectChanges version="1">
       <table><datetime>1556122543608</datetime><name>header</name>
       <row>
         <datetime>1556122543608</datetime><transactionType>UPDATE</transactionType>
         <column><name>status</name><newValue>14</newValue><oldValue>13</oldValue><mimeType>INT</mimeType></column>
         <column><name>no_i</name><primaryKey>true</primaryKey><newValue>16593</newValue><oldValue>16593</oldValue></column>
       </row></table>
     </businessObjectChanges>'

и используйте язык xpath для извлечения нужного поля

library(xml2)
xml = read_xml(txt)
xpath = "number(//name[text()='no_i']/following-sibling::newValue)"
xml_find_first(xml, xpath)

xpath немного продвинутый. number() приводит значение, указанное вложенным выражением, в число. //name[text()='no_i'] указывает путь через документ к узлу name, текст которого равен 'no_i'. following-sibling::newValue находит родственный узел (на том же уровне вложенности, что и только что идентифицированный узел name) с именем newValue; путь немного яснее с

> xml_path(xml_find_first(xml, "//name[text()='no_i']/following-sibling::newValue/text()"))
[1] "/businessObjectChanges/table/row/column[2]/newValue/text()"

Другой, более простой, одинаково эффективный xpath может быть

number(//primaryKey/../newValue)

Идея состоит в том, чтобы написать функцию, которая выполняет это для одного XML-документа

find_new_value <- function(txt, xpath) {
    xml = read_xml(txt)
    xml_find_first(xml, xpath)
}

и примените это к каждому элементу вашего (исправленного) XML-текста

xpath = "number(//primaryKey/../newValue)"
sapply(my_text$text1, find_new_value, xpath)

или в dplyr-land

my_text %>% mutate(value = find_new_value(text1, xpath))
0 голосов
/ 12 июня 2019

Если ваш номер будет всегда состоять из 5 цифр, то может помочь следующее.Вы можете изменить значение на {5,6}, если оно будет состоять из 5 и 6 цифр.

library(tidyverse)
my_text %>% 
  mutate(text1 = str_extract(text1, "\\b\\d{5}\\b"))
0 голосов
/ 12 июня 2019

Следуя вашему предложению, мы можем извлечь число после "no_i</name><primaryKey>true</primaryKey><newValue>", используя sub.

my_text$num <- sub(".*no_i</name><primaryKey>true</primaryKey><newValue>(\\d+).*", 
                   "\\1", my_text$text1)

my_text[c(1, 3)]
#  id   num
#1  1 16593
#2  2 10227
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...