strsplit неправильно разделяет по пробелу, когда второе слово короткое

Вопрос или проблема

Я хочу получить список видов из Викиданных, а затем извлечь конкретное название (второе слово) названия вида. Чтобы убедиться, что я не получаю ошибочные результаты, я хочу фильтровать только названия с двумя словами, так как все виды должны состоять только из двух слов. Я использовал strsplit, разделяя по пробелам (” “), чтобы проверить количество слов. Однако некоторые виды с двумя словами учитываются как имеющие одно слово. Я пробовал альтернативы для пробела (как описано здесь и здесь), но ничего не помогло.

Я использовал пакет WikidataQueryServiceR, чтобы получить названия видов из Викиданных. Запрос работает хорошо.

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

# Сколько слов в Leptobrachella eos?

# Установка пакетов
install.packages("WikidataQueryServiceR")
library(WikidataQueryServiceR)

# Выполнение запроса
# Этот запрос вернет каждый вид из рода Leptobrachella
df<-query_wikidata('SELECT DISTINCT ?item ?taxon_name WHERE {
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
  {
    SELECT DISTINCT ?item WHERE {
      ?item p:P171 ?statement0.
      ?statement0 ps:P171 wd:Q2142033.
    }
    LIMIT 100
  }
  OPTIONAL { ?item wdt:P225 ?taxon_name. }
}') # конец запроса

# Просмотр результатов и преобразование df в data.frame
df
df %>% data.class # изначально "spec_tbl_df"
df <- as.data.frame(df)
df[80,2] # возвращает "Leptobrachella eos", пример проблемы
df[80,2] %>% data.class # теперь "character"

# Попробуем разделить taxon_name по пробелам
strsplit(df[80,2]," ")
strsplit(df[80,2],"\\s+")
strsplit(df[80,2],"[[:space:]]")
strsplit(df[80,2],"[[:blank:]]")
# ни один из этих вариантов не сработал

# Виды с количеством слов, отличным от 2, попадают в датафрейм non_binomial
non_binomial <- df %>%  filter(sapply(strsplit(taxon_name, " "), length) != 2) # проверка видов с количеством слов, отличным от 2

Когда я проверяю датафрейм non_binomial, я получаю виды Leptobrachella feii, nyx, yeae и eos, все с четырьмя или менее буквами во втором слове. Может ли это короткое слово быть связано с проблемой? Есть ли лучший способ разбивать и считать слова в строке?

Я ожидал увидеть только виды с одним или тремя и более словами в датафрейме non_binomial.

Ответ или решение

Ваша проблема с использованием функции strsplit для разделения названий видов, вероятно, связана с тем, как обрабатываются пробелы в строке. В частности, если вторая часть названия имеет четыре или менее букв, это может вызвать неправильную обработку строки. Чтобы убедиться, что функция работает корректно, я рекомендую использовать более надёжный подход к подсчёту слов в строках.

Вот несколько шагов, которые можно предпринять, чтобы решить вашу задачу:

  1. Проверка наличия пробелов: Убедитесь, что в строке нет лишних пробелов (например, в начале или конце), а также последовательных пробелов между словами. Это можно сделать с помощью функции trimws и регулярных выражений.

  2. Использование регулярных выражений: Вместо strsplit вы можете использовать функцию stringr::str_count для подсчета количества слов в строке.

  3. Фильтрация данных: После того как вы убедитесь, что слова правильно разделяются, используйте фильтрацию для создания вашей таблицы non_binomial.

Вот переписанный пример вашего кода:

# Установите и загрузите пакеты
install.packages("WikidataQueryServiceR")
install.packages("dplyr")
install.packages("stringr")
library(WikidataQueryServiceR)
library(dplyr)
library(stringr)

# Запускаем запрос
df <- query_wikidata('SELECT DISTINCT ?item ?taxon_name WHERE {
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
  {
    SELECT DISTINCT ?item WHERE {
      ?item p:P171 ?statement0.
      ?statement0 ps:P171 wd:Q2142033.
    }
    LIMIT 100
  }
  OPTIONAL { ?item wdt:P225 ?taxon_name. }
}')

# Конвертируем df в data.frame
df <- as.data.frame(df)

# Убедимся, что нет лишних пробелов
df$taxon_name <- trimws(df$taxon_name)

# Проверим количество слов
word_count <- str_count(df$taxon_name, "\\S+")  # Подсчет ненулевых символов (слова)

# Фильтруем датафрейм для получения не бинарных видов
non_binomial <- df %>% filter(word_count != 2)

# Выводим не бинарный датафрейм
print(non_binomial)

В этом примере:

  • Мы используем trimws для удаления лишних пробелов.
  • Функция str_count с регулярным выражением "\\S+" считает количество слов в строке, игнорируя пробелы.
  • Мы фильтруем df по количеству слов в названиях видов.

Теперь, если вторая часть названия содержит короткое слово, оно не должно вызывать проблем с подсчетом слов. Испробуйте эти изменения, и вы должны получить корректный список видов с двумя словами.

Оцените материал
Добавить комментарий

Капча загружается...