Разделение столбца во фрейме данных на n-й экземпляр символа - PullRequest
0 голосов
/ 28 ноября 2018

У меня есть фрейм данных с несколькими столбцами, и один из этих столбцов заполнен каналами "|"и информацию, которую я пытаюсь получить.

Например:

View(Table$Column)
"|1||KK|12|Gold||4K|"
"|1||Rst|E|Silver||13||"
"|1||RST|E|Silver||18||"
"|1||KK|Y|Iron|y|12||"
"|1||||Copper|Cpr|||E"
"|1||||Iron|||12|F"

И т. Д. Для примерно 120К строк.Я пытаюсь раскопать все, что находится между 5-й и 6-й трубами в этой серии, но в своем собственном векторе столбцов, поэтому конечный результат выглядит следующим образом:

View(Extracted)
Gold
Silver
Silver
Iron
Copper
Iron

Я не хочуиспользовать RegEx.Мои инструменты ограничены только R здесь.У вас, ребята, есть какой-нибудь совет, как это преодолеть?

Спасибо.

Ответы [ 3 ]

0 голосов
/ 28 ноября 2018

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

df <- data.frame(x = c("|1||KK|12|Gold||4K|", "|1||Rst|E|Silver||13||"), stringsAsFactors = FALSE)
library(stringr)
stringr::str_split(df$x, "\\|", simplify = TRUE)[, 6]
0 голосов
/ 28 ноября 2018

1) Предполагая, что x определено воспроизводимо в примечании, в конце используйте read.table, как показано.Регулярные выражения или пакеты не используются.

read.table(text = Table$Column, sep = "|", header = FALSE, 
  as.is = TRUE, fill = TRUE)[6]

, что дает:

      V6
1   Gold
2 Silver
3 Silver
4   Iron
5 Copper
6   Iron

2) В этой альтернативе используется регулярное выражение (которое вопрос не задавался)) но на всякий случай вот решение по тидиру.Обратите внимание, что для этого требуется tidyr 0.8.2 или более поздней версии, поскольку более ранние версии tidyr не поддерживали NA в аргументе into=.

library(dplyr)
library(tidyr)

Table %>% 
  separate(Column, into = c(rep(NA, 5), "commodity"), sep = "\\|", extra = "drop")

, что дает:

  commodity
1      Gold
2    Silver
3    Silver
4      Iron
5    Copper
6      Iron

3) Это еще одно базовое решение.Вероятно, это не тот, который вы хотите, учитывая, что (1) намного проще, но я хотел посмотреть, сможем ли мы придумать второй подход в базе, который не использует регулярные выражения.Обратите внимание, что если split= аргумент strsplit равен "", то он обрабатывается специально и не является регулярным выражением.Он создает список, каждый из компонентов которого представляет собой вектор из отдельных символов.Каждый такой вектор передается анонимной функции, которая помечает | и символы в поле после него своим порядковым номером.Затем мы берем символы, соответствующие 5 (кроме первого, как |) и сворачиваем их вместе, используя paste.

data.frame(commodities = sapply(strsplit(Table$Column, ""), function(chars) {
  wx <- which(cumsum(chars == "|") == 5)
  paste(chars[seq(wx[2], tail(wx, 1))], collapse = "")
}), stringsAsFactors = FALSE)

, давая:

  commodities
1        Gold
2      Silver
3      Silver
4        Iron
5      Copper
6        Iron

Примечание

Table <- data.frame(Column = c("|1||KK|12|Gold||4K|",
  "|1||Rst|E|Silver||13||",
  "|1||RST|E|Silver||18||",
  "|1||KK|Y|Iron|y|12||",
  "|1||||Copper|Cpr|||E",
  "|1||||Iron|||12|F"), stringsAsFactors = FALSE)
0 голосов
/ 28 ноября 2018

1) Мы можем использовать strsplit из base R на разделителе | и извлечь 6-й элемент из list из vector s

sapply(strsplit(Table$Column, "|", fixed = TRUE), `[`, 6)
#[1] "Gold"   "Silver" "Silver" "Iron"   "Copper" "Iron"

2) Или, используя regex (снова из base R), используйте sub, чтобы извлечь 6-е слово

sub("^([|][^|]+){4}[|]([^|]*).*", "\\2", 
       gsub("(?<=[|])(?=[|])", "and", Table$Column, perl = TRUE))
#[1] "Gold"   "Silver" "Silver" "Iron"   "Copper" "Iron"  

data

Table <- structure(list(Column = c("|1||KK|12|Gold||4K|", 
 "|1||Rst|E|Silver||13||", 
 "|1||RST|E|Silver||18||", "|1||KK|Y|Iron|y|12||", "|1||||Copper|Cpr|||E", 
 "|1||||Iron|||12|F")), class = "data.frame", row.names = c(NA, 
 -6L))  
...