#r #dataframe
#r #фрейм данных
Вопрос:
Я пытаюсь разработать функцию, которая позволит мне вводить новые элементы во фрейм данных, а затем проверять, содержат ли они определенные слова.
df <- data.frame(keyword=c("He drives a Honda", "He goes to Ohio State"),
car=c(1,0), school=c(0,1))
df
keyword car school
He drives a Honda 1 0
He goes to Ohio State 0 1
В этом фрейме данных car и school являются двоичными значениями, которые содержат 1, если слово из вектора car / school является частью ключевого слова. Если в ключевом слове отсутствует слово, то присваивается 0.
car <- c("Honda", "Chevy", "Toyota", "Ford")
school <- c("Michigan", "Ohio State", "Missouri")
Я хочу использовать функцию для ввода новых ключевых слов во фрейм данных, одновременно повторяя ключевые слова для определенных значений из векторов car и school.
main <- function(keyword){
n = strsplit(as.character(keyword), " ")[[1]]
for( i in keyword ){
if( any(n==car) ){
df$car <- c(1)
}
if( any(n==school )){
df$school <- c(1)
}
}
}
Эта функция не завершена и выдает следующую ошибку. Поскольку векторы car и school имеют длину 3, похоже, это приводит к ошибке.
> main("He likes Ford and goes to Ohio State")
Warning message:
In n == school :
longer object length is not a multiple of shorter object length
Я также не уверен, как добавить значения 0/1 в df. Для ключевого слова «Ему нравится Ford и он едет в штат Огайо» у меня должно быть 1 как в колонках «автомобиль», так и в колонках «школа».
keyword car school
He drives a Honda 1 0
He goes to Ohio State 0 1
He likes Honda and goes to Ohio State 1 1
Пожалуйста, помогите.
Похоже, ifelse()
функция была бы действительно полезна для этой задачи, но я не смог ее должным образом реализовать.
Ответ №1:
Я думаю, что самый простой способ — использовать составное регулярное выражение:
library(stringr)
car <- c("Honda", "Chevy", "Toyota", "Ford")
school <- c("Michigan", "Ohio State", "Missouri")
car_match <- str_c(car, collapse = "|")
school_match <- str_c(school, collapse = "|")
df <- data.frame(keyword=c("He drives a Honda",
"He goes to Ohio State",
"He likes Ford and goes to Ohio State"))
main <- function(df) {
df$car <- str_detect(df$keyword, car_match)
df$school <- str_detect(df$keyword, school_match)
df
}
main(df)
Комментарии:
1. вау, это очень эффективно. Есть ли способ изменить FALSE / TRUE на 0/1?
2. Вы можете добавить 0 или использовать как.numeric. Но я сомневаюсь, что в этом есть какая-либо необходимость.
Ответ №2:
Несколько незначительных проблем, но их легко устранить с помощью пары %in%
. Также вам нужно специальное логическое выражение для учета «Штата Огайо», который отключался strsplit
из-за пробела.
df <- data.frame(keyword=c("He drives a Honda",
"He goes to Ohio State",
"He likes Ford and goes to Ohio State"),
car=0, school=0)
main <- function(df) {
car <- c("Honda", "Chevy", "Toyota", "Ford")
school <- c("Michigan", "Missouri")
for (i in 1:nrow(df)) {
Words = strsplit(as.character(df[i, 'keyword']), " ")[[1]]
if(any(Words %in% car)) df[i, 'car'] <- 1
if(any(Words == 'Ohio')) {
if(Words[which(Words == 'Ohio') 1] == 'State') df[i, 'school'] <- 1
}
if(any(Words %in% school)) df[i, 'school'] <- 1
}
return(df)
}
main(df)
keyword car school
1 He drives a Honda 1 0
2 He goes to Ohio State 0 1
3 He likes Ford and goes to Ohio State 1 1
Ответ №3:
Вот версия, которая, я полагаю, будет работать без необходимости указывать каждый поисковый запрос из двух слов вручную, как в случае «Штата Огайо» в решении wkmor1. Хитрость заключается в использовании grep
вместо:
main <- function(str,df){
carSearch <- unlist(lapply(car,grep,x=str,fixed=TRUE))
schoolSearch <- unlist(lapply(school,grep,x=str,fixed=TRUE))
t1 <- length(carSearch) != 0
t2 <- length(schoolSearch) != 0
if (t1 | t2){
newRow <- data.frame(keyword=str,car=ifelse(t1,1,0),
school=ifelse(t2,1,0))
df <- rbind(df,newRow)
return(df)
}
}