Tener un marco de datos como este:

df <- data.frame(id = c(1,2,3,4,5), keywords = c("google, yahoo, air, cookie", "cookie, air", "air, cookie", "google", "yahoo, google"))

¿Cómo es posible extraer una tabla como

df_binary_exist <- data.frame(id = c(1,2,3,4,5), google = c(1,0,0,1,1), yahoo = c(1,0,0,0,1), air = c(1,1,1,0,0), cookie = c(1,1,1,0,0))
df_binary_exist
  id google yahoo air cookie
1  1      1     1   1      1
2  2      0     0   1      1
3  3      0     0   1      1
4  4      1     0   0      0
5  5      1     1   0      0

Y de esta tabla encuentra las parejas más frecuentes?

df_frequency <- data.frame(couple = c("yahoo-google", "cookie-air"), freq = c(2,3))
df_frequency
        couple freq
1 yahoo-google    2
2   cookie-air    3
r
1
Elr Mant 10 may. 2019 a las 15:44

3 respuestas

La mejor respuesta

La primera parte se puede lograr usando separate_rows, count y spread

library(dplyr)
library(tidyr)

df1 <- df %>% separate_rows(keywords)

df1 %>%
  dplyr::count(id, keywords) %>%
  spread(keywords, n, fill = 0)

#     id   air cookie google yahoo
#   <dbl> <dbl>  <dbl>  <dbl> <dbl>
#1     1     1      1      1     1
#2     2     1      1      0     0
#3     3     1      1      0     0
#4     4     0      0      1     0
#5     5     0      0      1     1

Para la segunda parte, utilicé un método base R donde primero split keywords basado en la combinación id, paste de cada 2 elementos y contamos su frecuencia usando table .

data.frame(sort(table(unlist(sapply(split(df1$keywords, df1$id), function(x) 
   combn(sort(x), pmin(2, length(x)), paste, collapse = "-")))), decreasing = TRUE))

#           Var1 Freq
#1    air-cookie    3
#2  google-yahoo    2
#3    air-google    1
#4     air-yahoo    1
#5 cookie-google    1
#6  cookie-yahoo    1
#7        google    1
2
Ronak Shah 10 may. 2019 a las 13:13

Una posibilidad tidyverse podría ser:

df %>%
 mutate(keywords = strsplit(keywords, ", ", fixed = TRUE)) %>%
 unnest() %>%
 full_join(df %>%
            mutate(keywords = strsplit(keywords, ", ", fixed = TRUE)) %>%
            unnest(), by = c("id" = "id")) %>%
 filter(keywords.x != keywords.y) %>%
 count(keywords.x, keywords.y) %>%
 transmute(keywords = paste(pmax(keywords.x, keywords.y), pmin(keywords.x, keywords.y), sep = "-"),
           n) %>%
 distinct(keywords, .keep_all = TRUE)

  keywords          n
  <chr>         <int>
1 cookie-air        3
2 google-air        1
3 yahoo-air         1
4 google-cookie     1
5 yahoo-cookie      1
6 yahoo-google      2

Primero, divide la columna "palabras clave" en , y luego realiza una unión completa consigo mismo. En segundo lugar, filtra las filas donde los valores son los mismos ya que el OP está interesado en pares de valores. Tercero, cuenta el número de ocurrencias de pares. Finalmente, crea una variable ordenada de pares y mantiene solo las filas distintas basadas en esta variable.

O la misma usando separate_rows():

df %>%
 separate_rows(keywords) %>%
 full_join(df %>%
            separate_rows(keywords), by = c("id" = "id")) %>%
 filter(keywords.x != keywords.y) %>%
 count(keywords.x, keywords.y) %>%
 transmute(keywords = paste(pmax(keywords.x, keywords.y), pmin(keywords.x, keywords.y), sep = "-"),
           n) %>%
 distinct(keywords, .keep_all = TRUE)
2
tmfmnk 10 may. 2019 a las 13:24

Podemos hacer esto fácilmente con

library(qdapTools)
cbind(df[1],  mtabulate(strsplit(as.character(df$keywords), ", ")))
#  id air cookie google yahoo
#1  1   1      1      1     1
#2  2   1      1      0     0
#3  3   1      1      0     0
#4  4   0      0      1     0
#5  5   0      0      1     1
1
akrun 10 may. 2019 a las 13:58