Использовать регулярное выражение для вставки пробела между сложенными словами

Я работаю над choropleth в R и должен иметь возможность сопоставлять имена состояний с match.map(). В наборе данных я использую палки многословных имен вместе, например, NorthDakota и DistrictOfColumbia.

Как я могу использовать регулярные выражения для вставки пробела между нижними верхними буквами? Я успешно добавил пробел, но не смог сохранить буквы, указывающие, куда идет пробел.

places = c("NorthDakota", "DistrictOfColumbia")
gsub("[[:lower:]][[:upper:]]", " ", places)
[1] "Nort akota"       "Distric  olumbia"

Ответ 1

Используйте скобки для захвата согласованных выражений, затем \n (\\n в R) для их получения:

places = c("NorthDakota", "DistrictOfColumbia")
gsub("([[:lower:]])([[:upper:]])", "\\1 \\2", places)
## [1] "North Dakota"         "District Of Columbia"

Ответ 2

Вы хотите использовать группы захвата для захвата в согласованный контекст, чтобы вы могли вернуться к каждой согласованной группе в своем замещающем вызове. Для доступа к группам перед двумя обратными косыми чертами \\ следует группа #.

> places = c('NorthDakota', 'DistrictOfColumbia')
> gsub('([[:lower:]])([[:upper:]])', '\\1 \\2', places)
# [1] "North Dakota"         "District Of Columbia"

Другой способ: включить PCRE с помощью perl=T и использовать lookaround утверждения.

> places = c('NorthDakota', 'DistrictOfColumbia')
> gsub('[a-z]\\K(?=[A-Z])', ' ', places, perl=T)
# [1] "North Dakota"         "District Of Columbia"

Объяснение

Управляющая последовательность \K сбрасывает исходную точку сообщенного соответствия, и все ранее использованные символы больше не включаются. В основном (выбрасывает все, что соответствует ему).

[a-z]       # any character of: 'a' to 'z'
\K          # '\K' (resets the starting point of the reported match)
(?=         # look ahead to see if there is:
  [A-Z]     #   any character of: 'A' to 'Z'
)           # end of look-ahead