Условное разбиение строки кадра данных на основе второго пробела - PullRequest
0 голосов
/ 15 января 2019

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

                           test22 Ticker
1        Current SharePrice $6.57    MFM
2               Current NAV $7.11    MFM
3 Current Premium/Discount -7.59%    MFM
4        52WkAvg SharePrice $6.55    MFM
5               52WkAvg NAV $7.21    MFM
6 52WkAvg Premium/Discount -9.19%    MFM

По сути, если конечным результатом будет фрейм данных с тремя столбцами, а поле цена /% будет отдельным отдельным столбцом. Спасибо!

Ответы [ 3 ]

0 голосов
/ 15 января 2019

Вот вариант с использованием strsplit

data.frame(do.call(rbind, strsplit(df$test22, '\\s(?!.*\\s)', perl = TRUE)), 
           Ticker=df$Ticker)
#                         X1     X2 Ticker
# 1       Current SharePrice  $6.57    MFM
# 2              Current NAV  $7.11    MFM
# 3 Current Premium/Discount -7.59%    MFM
# 4       52WkAvg SharePrice  $6.55    MFM
# 5              52WkAvg NAV  $7.21    MFM
# 6 52WkAvg Premium/Discount -9.19%    MFM

Или используя gsub

gsub('.*\\s.*?\\s(.*)','\\1', df$test22, perl = TRUE)
# [1] "$6.57"  "$7.11"  "-7.59%" "$6.55"  "$7.21"  "-9.19%"
# or if factors
# gsub('.*\\s.*?\\s(.*)','\\1', as.character(df$test22), perl = TRUE)

Преимущество второго состоит в том, что он действительно учитывает второй символ пробела (в отличие от последнего пробела).

0 голосов
/ 15 января 2019

Вот вариант с использованием dplyr и stringr:

library(dplyr)
library(stringr)

data <-
  tibble(test22 = c("Current SharePrice $6.57",
                    "Current NAV $7.11",
                    "Current Premium/Discount -7.59%",
                    "52WkAvg SharePrice $6.55",
                    "52WkAvg NAV $7.21",
                    "52WkAvg Premium/Discount -9.19%"),
         Ticker = "MFM")

data %>% 
  mutate(category = str_replace(test22, "^(.+ .+) (.+)$", "\\1"),
         price_pc = str_replace(test22, "^(.+ .+) (.+)$", "\\2"))


# A tibble: 6 x 4
test22                          Ticker category                 price_pc
<chr>                           <chr>  <chr>                    <chr>   
1 Current SharePrice $6.57        MFM    Current SharePrice       $6.57   
2 Current NAV $7.11               MFM    Current NAV              $7.11   
3 Current Premium/Discount -7.59% MFM    Current Premium/Discount -7.59%  
4 52WkAvg SharePrice $6.55        MFM    52WkAvg SharePrice       $6.55   
5 52WkAvg NAV $7.21               MFM    52WkAvg NAV              $7.21   
6 52WkAvg Premium/Discount -9.19% MFM    52WkAvg Premium/Discount -9.19% 

EDIT: объяснение используемого регулярного выражения

Игнорирование скобок на секунду:

^ = начало строки

. = любой символ, кроме новой строки

+ = хотя бы один из предыдущих символов (в данном случае любой символ, кроме новой строки)

$ = конец строки

Итак, "^(.+ .+) (.+)$" ищет строки, которые начинаются, имеют несколько символов, затем пробел, затем несколько символов, затем пробел, затем еще несколько символов, затем конец.

Скобки добавляются как «группы захвата», что означает, что запрос «запоминает» ту часть строки, которая представлена ​​этими скобками, и может быть извлечена путем обращения к порядку скобок. Следовательно, "\\1" возвращает то, что было захвачено первой скобкой, а "\\2" возвращает то, что было захвачено второй.

Хорошим ресурсом для изучения Regex является Regexr .

0 голосов
/ 15 января 2019

Один из вариантов в базе - создать разделитель , с sub, а затем использовать read.csv:

out <- cbind(read.csv(text = sub(" (\\S+)$", ",\\1", df1$test22), 
       header = FALSE, stringsAsFactors = FALSE), df1[2])
out
#.                       V1     V2 Ticker
#1       Current SharePrice  $6.57    MFM
#2              Current NAV  $7.11    MFM
#3 Current Premium/Discount -7.59%    MFM
#4       52WkAvg SharePrice  $6.55    MFM
#5              52WkAvg NAV  $7.21    MFM
#6 52WkAvg Premium/Discount -9.19%    MFM

Или используя extract из tidyr

library(tidyverse)
df1 %>% 
     extract(test22, into = c("V1", "V2"), "^(\\S+\\s+\\S+)\\s+(.*)")
#                        V1     V2 Ticker
#1       Current SharePrice  $6.57    MFM
#2              Current NAV  $7.11    MFM
#3 Current Premium/Discount -7.59%    MFM
#4       52WkAvg SharePrice  $6.55    MFM
#5              52WkAvg NAV  $7.21    MFM
#6 52WkAvg Premium/Discount -9.19%    MFM

данные

df1 <- structure(list(test22 = c("Current SharePrice $6.57", "Current NAV $7.11", 
  "Current Premium/Discount -7.59%", "52WkAvg SharePrice $6.55", 
 "52WkAvg NAV $7.21", "52WkAvg Premium/Discount -9.19%"), Ticker = c("MFM", 
 "MFM", "MFM", "MFM", "MFM", "MFM")), class = "data.frame", row.names = c("1", 
  "2", "3", "4", "5", "6"))
...