str_extract () дает другой результат вызова вектора из dataframe - R - PullRequest
1 голос
/ 22 апреля 2019

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

x <- c("De 1 a 2 semanas", "De 3 a 4 semanas", "Más de 6 semanas", "Menos de 1 semana")

И я пытаюсь извлечь каждое значение по уникальному идентификатору:

str_extract(x, "1 sem|1 a 2|3 a 4|5 a 6|de 6 sem")

И это работает:

[1] "1 a 2"    "3 a 4"    "de 6 sem" "1 sem"  

Однако, когда я вызываю вектор из кадра данных:

> x$PVS9
[1] "De 1 a 2 semanas"  "De 3 a 4 semanas"  "Más de 6 semanas"  "Menos de 1 semana"
> x$PVS9 <- str_extract(x$PVS9, "1 sem|1 a 2|3 a 4|5 a 6|de 6 sem")
> x$PVS9
[1] "1 a 2" NA      NA      "1 sem"

Почему он дает эти два NA?

PS: Вам может пригодиться этот вопрос (и его ответ).

Вот минимальный воспроизводимый пример:

> dput(x)
structure(list(PVS9 = c("De 1 a 2 semanas", "De 3 a 4 semanas", 
"Más de 6 semanas", "Menos de 1 semana"), n = c(1L, 1L, 1L, 3L
), Porcentaje = c(0.17, 0.17, 0.17, 0.5)), row.names = c(NA, 
-4L), class = c("tbl_df", "tbl", "data.frame"))

Токовый выход:

> str_extract(x$PVS9, "1 sem|1 a 2|3 a 4|5 a 6|de 6 sem")
[1] "1 a 2" NA      NA      "1 sem"

Желаемый вывод:

[1] "1 a 2"    "3 a 4"    "de 6 sem" "1 sem"  

Дополнительная информация:

Информация о сеансе:

> sessionInfo()
R version 3.5.2 (2018-12-20)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)

Matrix products: default

locale:
[1] LC_COLLATE=Spanish_Chile.1252  LC_CTYPE=Spanish_Chile.1252    LC_MONETARY=Spanish_Chile.1252 LC_NUMERIC=C                   LC_TIME=Spanish_Chile.1252    

Класс:

> class(x$PVS9)
[1] "character"

Кодирование:

> Encoding(x$PVS9)
[1] "unknown" "unknown" "unknown" "unknown"

> guess_encoding(x$PVS9)
# A tibble: 3 x 2
  encoding   confidence
  <chr>           <dbl>
1 ISO-8859-1       0.98
2 ISO-8859-2       0.88
3 ISO-8859-9       0.33

Также:

> x$PVS9 == y
[1]  TRUE FALSE FALSE  TRUE

Я думал решить эту смену кодировки вектора. Это возможно? Если нет, есть ли другой способ?

РЕДАКТИРОВАТЬ: Требуется дополнительная информация.

Что R думает, что это:

> sapply(x$PVS9, charToRaw)
$`De 1 a 2 semanas`
 [1] 44 65 20 31 20 61 20 32 20 73 65 6d 61 6e 61 73

$`De 3 a 4 semanas`
 [1] 44 65 20 33 a0 61 20 34 a0 73 65 6d 61 6e 61 73

$`Más de 6 semanas`
 [1] 4d e1 73 20 64 65 20 36 a0 73 65 6d 61 6e 61 73

$`Menos de 1 semana`
 [1] 4d 65 6e 6f 73 20 64 65 20 31 20 73 65 6d 61 6e 61

1 Ответ

1 голос
/ 23 апреля 2019

По крайней мере, часть проблемы связана с наличием странных символов, которые для человека выглядят так же, как обычные символы, но отличаются от компьютера:

charToRaw преобразует строку символов в необработанные шестнадцатеричные значения, которые представляют символы для компьютера. Давайте посмотрим на 2-ю строку, которая вам не подходит, и сравним ее с тем, что я вижу на моем компьютере (где соответствует ):

#  This does NOT match
$`De 3 a 4 semanas`
 [1] 44 65 20 33 a0 61 20 34 a0 73 65 6d 61 6e 61 73

# This does match
$`De 3 a 4 semanas`
 [1] 44 65 20 33 20 61 20 34 20 73 65 6d 61 6e 61 73

Есть разница: 5-е и 9-е числа 20 в моей системе и a0 в вашей. Что это значит? Вы можете использовать intToUtf8, чтобы увидеть, как эти символы отображаются, хотя сначала мы должны преобразовать из шестнадцатеричного в десятичное :

# 20 in hexidecimal
# is 32 in decimal
intToUtf8(32)
[1] " "


# a0 in hexidecimal
# is 160 in decimal
intToUtf8(160)
[1] " "

Так что они оба выглядят для нас как пробелы, но для компьютера они совершенно разные персонажи. Если вы посмотрите на эти числа в справочной таблице UTF-8 , вы увидите, что 32 - это обычный пробел, а 160 - это пробел без перерывов:

32  SPACE
160 NO-BREAK SPACE

Неразрывные пробелы (также известные как &nbsp) часто встречаются в документах HTML для создания более широких пробелов, которые (так как несколько последовательных нормальных пробелов сокращаются до одного).


Итак, как мы можем это исправить? Для начала давайте воспроизведем ваши данные:

bad_str2 <- paste0('De 3', intToUtf8(160), 'a', intToUtf8(160), '4 semanas')

# Looks the same
bad_str2
[1] "De 3 a 4 semanas"

# But has the non-breaking spaces
charToRaw(bad_str2)
 [1] 44 65 20 33 c2 a0 61 c2 a0 34 20 73 65 6d 61 6e 61 73

# Regex does not work:
str_extract(bad_str2, "1 sem|1 a 2|3 a 4|5 a 6|de 6 sem")
[1] NA

Теперь мы можем использовать gsub для замены неразрывных пробелов обычными пробелами:

# The \u prefix means interpret the following Hexidecimal code as a character
# So \ua0 means, the character specified by hex code 'a0', which is the nbsp
fixed_str <- gsub("\ua0", " ", bad_str2, fixed = TRUE)

# Still looks the same
fixed_str
[1] "De 3 a 4 semanas"

# But regex works now!
str_extract(fixed_str, "1 sem|1 a 2|3 a 4|5 a 6|de 6 sem")
[1] "3 a 4"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...