Как рассчитать взвешенную сумму слов в столбцах? - PullRequest
0 голосов
/ 11 декабря 2018

Этот вопрос является модифицированной версией подсчета определенных слов по нескольким столбцам в R , но с добавленной сложностью определения различных весов для определенных столбцов.Как сделать так, чтобы некоторые столбцы считались как 1, а другие - как 0.5?

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

df <- data.frame(id=c(1, 2, 3, 4, 5), staple_1=c("potato",       "potato","rice","fruit","coffee"), 
             staple2_half1=c("yams","beer","potato","rice","yams"), 
             staple2_half2=c("potato","rice","yams","rice","yams"), 
             staple_3=c("rice","peanuts","fruit","fruit","rice"))
potato<-c("potato")
yams<-c("yams")
staples<-c("potato","cassava","rice","yams")

дает:

id staple_1 staple2_half1 staple2_half2 staple_3
 1   potato          yams        potato     rice
 2   potato          beer          rice  peanuts
 3     rice        potato          yams    fruit
 4    fruit          rice          rice    fruit
 5   coffee          yams          yams     rice

Теперь я хочу создать 2 дополнительных столбца, суммирующих значения «potato» и «yams», ноизменив следующий код так, чтобы любые значения из столбца «half» (staple2_half1 и staple2_half2) учитывались только как 0.5 вместо 1.

Неправильный результат с использованием исходного ответа:

df$staples <- apply(df, 1, function(x) sum(staples %in% x))
df$potato<- apply(df, 1, function(x) sum(potato %in% x))
df$yams<- apply(df, 1, function(x) sum(yams %in% x))

Дает:

  id staple_1 staple2_half1 staple2_half2 staple_3 staples potato yams
  1   potato          yams        potato     rice       3      1    1
  2   potato          beer          rice  peanuts       2      1    0
  3     rice        potato          yams    fruit       3      1    1
  4    fruit          rice          rice    fruit       1      0    0
  5   coffee          yams          yams     rice       2      0    1

Желаемый результат на основе взвешенного количества:

  id staple_1 staple2_half1 staple2_half2 staple_3 staples potato yams
  1   potato          yams        potato     rice       3     1.5  0.5
  2   potato          beer          rice  peanuts      1.5      1    0
  3     rice        potato          yams    fruit       2     0.5  0.5
  4    fruit          rice          rice    fruit       1      0    0
  5   coffee          yams          yams     rice       2      0    1

Ответы [ 2 ]

0 голосов
/ 11 декабря 2018

Если вы apply функция %in% над столбцами df[, -1], вы получите матрицу истинных и ложных значений.Затем, чтобы сделать взвешенную сумму, вы можете умножить эту матрицу на вектор весов.

words <- data.frame(staples, potato, yams)
weights <- 1 - 0.5*grepl('half', names(df[, -1]))

df[names(words)] <- 
  lapply(words, function(x) apply(df[, -1], 2, `%in%`, x) %*% weights)


df

#   id staple_1 staple2_half1 staple2_half2 staple_3 staples potato yams
# 1  1   potato          yams        potato     rice     3.0    1.5  0.5
# 2  2   potato          beer          rice  peanuts     1.5    1.0  0.0
# 3  3     rice        potato          yams    fruit     2.0    0.5  0.5
# 4  4    fruit          rice          rice    fruit     1.0    0.0  0.0
# 5  5   coffee          yams          yams     rice     2.0    0.0  1.0

Пример того, как будет выглядеть результат apply(df1[, -1], 2, ...

apply(df[, -1], 2, `%in%`, potato)
#      staple_1 staple2_half1 staple2_half2 staple_3
# [1,]     TRUE         FALSE          TRUE    FALSE
# [2,]     TRUE         FALSE         FALSE    FALSE
# [3,]    FALSE          TRUE         FALSE    FALSE
# [4,]    FALSE         FALSE         FALSE    FALSE
# [5,]    FALSE         FALSE         FALSE    FALSE

apply(df[, -1], 2, `%in%`, potato) %*% weights
#      [,1]
# [1,]  1.5
# [2,]  1.0
# [3,]  0.5
# [4,]  0.0
# [5,]  0.0
0 голосов
/ 11 декабря 2018

Множество способов сделать это, но вот один, использующий Tidyverse.«Собрав» данные так, чтобы все скрепки были в одном столбце, я думаю, что легче применить правильный вес.

library(tidyverse)

df <- data.frame(id=c(1, 2, 3, 4, 5), staple_1=c("potato",       "potato","rice","fruit","coffee"), 
                 staple2_half1=c("yams","beer","potato","rice","yams"), 
                 staple2_half2=c("potato","rice","yams","rice","yams"), 
                 staple_3=c("rice","peanuts","fruit","fruit","rice"))
potato<-c("potato")
yams<-c("yams")
staples<-c("potato","cassava","rice","yams")


freqs <- df %>% 
  mutate_if(is.factor, as.character) %>% # avoids a warning about converting types
  gather("column", "item", -id) %>%
  mutate(scalar = if_else(str_detect(column, "half"), 0.5, 1)) %>%
  group_by(id) %>%
  summarize(
    staples = sum(item %in% staples * scalar),
    potato = sum(item %in% potato * scalar),
    yams = sum(item %in% yams * scalar)
  )

left_join(df, freqs, by = "id")
#>   id staple_1 staple2_half1 staple2_half2 staple_3 staples potato yams
#> 1  1   potato          yams        potato     rice     3.0    1.5  0.5
#> 2  2   potato          beer          rice  peanuts     1.5    1.0  0.0
#> 3  3     rice        potato          yams    fruit     2.0    0.5  0.5
#> 4  4    fruit          rice          rice    fruit     1.0    0.0  0.0
#> 5  5   coffee          yams          yams     rice     2.0    0.0  1.0

Создано в 2018-12-11 с помощью представпакет (v0.2.1)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...