Разделить строку на два подшаблона в data.frame

У меня есть вектор символов:

s <- "0 / 10 %(% 1 / 11 %-% 2 / 12 %)% 3 / 13"

Цель состоит в том, чтобы разделить его как на /, так и на %*% на точки (x, y) и символы z:

data.frame(x = c(0,1,2,3), y = c(10,11,12,13), z = c("(", "-", ")", NA),
           stringsAsFactors = FALSE)
  x  y    z
1 0 10    (
2 1 11    -
3 2 12    )
4 3 13 <NA>

Примечания:

  • / разделяет точки: я хочу разделить x / y на x-часть и y-часть.
  • Второе разделение %*% должно идти в столбец z символов, но без %;

Я пробовал разные версии strsplit безуспешно:

trimws(unlist(strsplit(s, "[/(%*%)]")))
[1] "0" "0" ""  ""  "1" "1" "-" "2" "2" ""  ""  "3" "3"

Проблемы:

  • - не попадается (%*%), почему?
  • У меня есть пустые части строки, почему?
  • Я понятия не имею, как хранить splits в столбце z

Обратите внимание, что strsplit(s, '%[(-)]%') отбрасывает ваши шаблоны разделения, что было бы нормально для '/', но не для захвата среднего символа между процентами. Если вы гарантируете наличие пробела после нужного процента, вы можете просто сделать strsplit(s, '% '); в противном случае вам понадобится регулярное выражение с утверждением правого просмотра для цифр. Проще и понятнее сделать два разбиения, сделать первое разбиение на правом проценте '%'.

smci 09.04.2019 13:28
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
63
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Это решает вашу проблему:


str <- "0 / 10 %(% 1 / 11 %-% 2 / 12 %)% 3 / 13"

str_sub <- gsub("[%/]","",str) #sub all % and / with ""
str_split <- strsplit(str_sub,"\\s+")[[1]] #split by whitespace
str_corr <- c(str_split,rep(NA,3-length(str_split) %% 3)) #correct length, fill the end with NAs

df <- as.data.frame(matrix(str_corr,ncol=3,byrow=TRUE)) #convert to data.frame via matrix
colnames(df) <- c("x","y","z") #set colnames

Created on 2019-04-09 by the reprex package (v0.2.1)

К вашему первому выпуску:

  1. %*% не захватывает -, потому что вы просите регулярное выражение повторить % 0 или более раз (со звездочкой *), но не запрашиваете -.

Это тонко, потому что strsplit(s, '%[(-)]%') отбрасывает ваши шаблоны разделения, что было бы нормально для '/', но не для захвата среднего символа между процентами. Если вы гарантируете наличие пробела после нужного процента, вы можете просто выполнить strsplit(s, '% '); в противном случае вам понадобится регулярное выражение с утверждением правого просмотра для цифр.

Проще и понятнее сделать два разбиения: сделайте первое разбиение на правом проценте '%':

s2 <- strsplit(s, '% ')[[1]]

"0 / 10 %(" "1 / 11 %-" "2 / 12 %)" "3 / 13"

Теперь вы делаете второе разделение как на символы «/», так и на символы левого процента:

> strsplit(s2, '[%/]')

[[1]]
[1] "0 "   " 10 " "("   

[[2]]
[1] "1 "   " 11 " "-"   

[[3]]
[1] "2 "   " 12 " ")"   

[[4]]
[1] "3 "  " 13"

Небольшая проблема с тем, что он рваный; последняя строка не имеет символа. Поскольку в вашем случае кажется безопасным предположить, что это происходит только в конце строки, проще всего добавить символ конца строки '%$%' (обратите внимание на завершающий пробел), а затем сопоставить $ -> NA позже.

Другие вопросы по теме