Применить пользовательскую функцию к одному df, используя один столбец в другом df - PullRequest
0 голосов
/ 13 июля 2020

df1 (1500 строк) показывает вопросы, процент правильных ответов и количество попыток задать вопрос:

qtitle                                   avg_correct                       attempts  

"Asthma and exercise, question 1"         54.32                            893
"COVID-19 and ventilators, q 3"           23.60                            143
"Pedestrian vs. car MVCs"                 74.19                            227
"Hemophilia and monoclonal Abs"           34.56                            78
"COVID-19 and droplets"                   83.21                            234

Используя библиотеку tidytext, наиболее часто встречающиеся слова в столбце qtitle были определены и подсчитаны по частоте до создать второй фрейм данных (df2, с 320 строками).

word                n
COVID-19            68
Trauma              57
Hemophilia          46

Я хотел бы использовать каждую запись в слове col в df2, чтобы соответствовать словам в заголовках вопросов в df1 (qtitle) и найти среднее значение avg_correct, сумма попыток и частота поискового запроса (n в df2). [ie., сопоставить df2 с df1 с помощью пользовательской функции]

word            avg_correct        attempts              count(n)
COVID-19        55.23              456                   68
Hemophilia      45.92              123                   46

Это не работа (очевидно)

correct_by_terms <- function(x) {
  filter(df1, str_detect(title, x))
  result <- summarise(df1, mean = mean(average), n = n(), x = x)
  return (result)
}
frequent_terms_by_correct_percent<- map_df(df2$word, correct_by_terms)

Ответы [ 3 ]

2 голосов
/ 13 июля 2020

Вот что-то, использующее основание R для вычисления того, что вы просите.

# get total number of correct per question
df1$correct <- df1$avg_correct * df1$attempts / 100

# initialize attempts and correct to 0
df2$attempts <- 0
df2$correct <- 0

# loop over df2
for (df2_index in 1:nrow(df2)){
  df2_row <- df2[df2_index,]
  # loop over df1
  for (df1_index in 1:nrow(df1)){
    df1_row <- df1[df1_index,]
    # if df1 qtitle contains df2 word
    if(grepl(df2_row$word, df1_row$qtitle, fixed = T)){
      df2[df2_index ,"attempts"] <- df2[df2_index ,"attempts"] + df1_row$attempts
      df2[df2_index ,"correct"] <- df2[df2_index ,"correct"] + df1_row$correct
    }
  }
}

df2$avg_correct = (df2$correct / df2$attempts) * 100
1 голос
/ 13 июля 2020

Вы можете попробовать использовать этот базовый подход R. Используя sapply, мы l oop для каждого word в df2, сопоставляем его с grepl в заголовке вопроса в df1 и возвращаем mean из avg_correct и sum из * 1009. * для этих индексов.

cbind(df2, t(sapply(df2$word, function(x) {
        inds <- grepl(paste0('\\b', x, '\\b'), df1$qtitle)
        c(avg_correct = mean(df1$avg_correct[inds]), 
          attempts = sum(df1$attempts[inds]))
})))
0 голосов
/ 19 июля 2020

Если все слова, которые вы хотите сопоставить, - это слова , которые можно идентифицировать посредством токенизации, как в приведенных вами примерах, я бы:

  • tokenize,
  • внутреннее соединение, затем
  • group_by() и суммируйте.
library(tidyverse)
library(tidytext)

df1 <- tribble(~qtitle,                                ~avg_correct,   ~attempts,  
               "Asthma and exercise, question 1",      54.32,          893,
               "COVID19 and ventilators, q 3",        23.60,          143,
               "Pedestrian vs. car MVCs",              74.19,          227,
               "Hemophilia and monoclonal Abs",        34.56,          78,
               "COVID19 and droplets",                83.21,          234
)

df2 <- tribble(~word,              ~n,
               "COVID19",         68,
               "Trauma",           57,
               "Hemophilia",       46) %>%
  mutate(word = tolower(word))

df1 %>% 
  unnest_tokens(word, qtitle) %>%
  inner_join(df2) %>%
  group_by(word) %>%
  summarise(avg_correct = mean(avg_correct),
            attempts = sum(attempts),
            n = first(n))
#> Joining, by = "word"
#> `summarise()` ungrouping output (override with `.groups` argument)
#> # A tibble: 2 x 4
#>   word       avg_correct attempts     n
#>   <chr>            <dbl>    <dbl> <dbl>
#> 1 covid19           53.4      377    68
#> 2 hemophilia        34.6       78    46

Создано 18.07.2020 с помощью пакета REPEX (v0.3.0)

...