Вопрос или проблема
Я хочу получить список видов из Викиданных, а затем извлечь конкретное название (второе слово) названия вида. Чтобы убедиться, что я не получаю ошибочные результаты, я хочу фильтровать только названия с двумя словами, так как все виды должны состоять только из двух слов. Я использовал 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
для разделения названий видов, вероятно, связана с тем, как обрабатываются пробелы в строке. В частности, если вторая часть названия имеет четыре или менее букв, это может вызвать неправильную обработку строки. Чтобы убедиться, что функция работает корректно, я рекомендую использовать более надёжный подход к подсчёту слов в строках.
Вот несколько шагов, которые можно предпринять, чтобы решить вашу задачу:
-
Проверка наличия пробелов: Убедитесь, что в строке нет лишних пробелов (например, в начале или конце), а также последовательных пробелов между словами. Это можно сделать с помощью функции
trimws
и регулярных выражений. -
Использование регулярных выражений: Вместо
strsplit
вы можете использовать функциюstringr::str_count
для подсчета количества слов в строке. -
Фильтрация данных: После того как вы убедитесь, что слова правильно разделяются, используйте фильтрацию для создания вашей таблицы
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
по количеству слов в названиях видов.
Теперь, если вторая часть названия содержит короткое слово, оно не должно вызывать проблем с подсчетом слов. Испробуйте эти изменения, и вы должны получить корректный список видов с двумя словами.