Очистить столбцы, которые содержат списки, как переменные, которые являются пустыми / NULL / NA в R? - PullRequest
0 голосов
/ 21 января 2019

Учитывая следующий фрейм данных со списками в качестве значений:

df <- structure(list(keys.userId = c("9875", "5465", 
"1234", "4567", "8910"), user_data.SSIDs = list(
    c("qjJf5iZtYboSPvqe1oa/xg==", "ul7kroLEB2cZx6AMGhjnrA==", 
    "OYRT/hYu1Dl3/S5WIWyLHA==", "HFiSH/Tu0RSaQgIbDEZfeA==", "gUBxBfxjGdyPNzqYX7t6nA==", 
    "m7UqzqaXUm1GkXMbxf+SJw==", "KjxvZwsVCNSTtXXKiidmjw==", "3UOqe+4qPVZYXvja8GBEqg==", 
    "a9Ba8b19tY/bprM7WA326A==", "uStr9Fg+JlU9B+hdBCafZg==", "i9J11W00HFmoeCDObOfSdA==", 
    "A9vOz8zSrwDiQcKv8hk64Q==", "/8QeMoqFwd/eJ+/6NKk1iQ==", "HbyJqQxUfH6oiW3skqPzGQ==", 
    "51H9RcZmdRgkgg4X6U/mhQ==", "dwat86ppe1b/WXSaGi8r3w==", "yBCbMedxtZdiGFXmTfk2eQ==", 
    "wKSIsw3sDPRQhLIhdQkBJw==", "3LkFUenHOXWL4Be5T4XmaQ==", "Krni6eGQUnZuL/jU0MzKNA==", 
    "Wt9BCH4guyC4oSIHwE8XGA==", "rbgxp/3YPdHiownOdZHf+A==", "34rmNRgT/xFDXIDwHKIY6Q==", 
    "pT3zFcGdlJKmR+khJLMoVw==", "eni3X9I2B4KRK+sho2MbjA==", "sxuba/1Brg4CrYL8AFv8ZQ==", 
    "EYIxPOXPVvop99YD0vjXPA==", "JC1xqrtmQEaohwzviYDFYA==", "qv+cfEEqsIGrDFuEqpkQuw==", 
    "d3xXMR1RDKZdrDwQd97kNQ==", "qU1JULumBTqw+m/rLr4E7A==", "teDCJvNdyjktWD6leDpCmw==", 
    "ytSBHvzbEACq56aEHZlXEw==", "eV7WGimPD01weRI19ojO3g==", "vNkJyD9KOzOprGkYyfViMA==", 
    "r8jjZXWyax7JPfJUPFwRTQ==", "rJ1N3ONwDBK+jwFf+7xeHg==", "2xPbTqIww1KI/tVL2UH1cw==", 
    "1hk1AOU4DZXV52Auyr2FHA==", "aNH8uS5nrlwcHb8rLdZeXQ==", "5JPQs2z4N1Dru0dGI9ImBQ==", 
    "nbQIn5G4uyl8b1+A6aVkQg==", "A/UcwEccakKDuiATgoP1NA==", "JC57Ib2V7fOU/CgBk2R41g==", 
    "PsI8Ys++JveA+SuafbB8pg==", "eXiuBymYN+tcbjtpM9Vxmg==", "jEdP3Rs02d/4UE8G1GeE3A=="
    ), NULL, c("qjJf5iZtYboSPvqe1oa/xg==", "ul7kroLEB2cZx6AMGhjnrA==", 
    "OYRT/hYu1Dl3/S5WIWyLHA==", "HFiSH/Tu0RSaQgIbDEZfeA==", "gUBxBfxjGdyPNzqYX7t6nA==", 
    "m7UqzqaXUm1GkXMbxf+SJw==", "KjxvZwsVCNSTtXXKiidmjw==", "3UOqe+4qPVZYXvja8GBEqg==", 
    "a9Ba8b19tY/bprM7WA326A==", "uStr9Fg+JlU9B+hdBCafZg==", "i9J11W00HFmoeCDObOfSdA==", 
    "A9vOz8zSrwDiQcKv8hk64Q==", "/8QeMoqFwd/eJ+/6NKk1iQ==", "HbyJqQxUfH6oiW3skqPzGQ==", 
    "51H9RcZmdRgkgg4X6U/mhQ==", "dwat86ppe1b/WXSaGi8r3w==", "yBCbMedxtZdiGFXmTfk2eQ==", 
    "wKSIsw3sDPRQhLIhdQkBJw==", "3LkFUenHOXWL4Be5T4XmaQ==", "Krni6eGQUnZuL/jU0MzKNA==", 
    "Wt9BCH4guyC4oSIHwE8XGA==", "rbgxp/3YPdHiownOdZHf+A==", "34rmNRgT/xFDXIDwHKIY6Q==", 
    "pT3zFcGdlJKmR+khJLMoVw==", "eni3X9I2B4KRK+sho2MbjA==", "sxuba/1Brg4CrYL8AFv8ZQ==", 
    "EYIxPOXPVvop99YD0vjXPA==", "JC1xqrtmQEaohwzviYDFYA==", "qv+cfEEqsIGrDFuEqpkQuw==", 
    "d3xXMR1RDKZdrDwQd97kNQ==", "qU1JULumBTqw+m/rLr4E7A==", "teDCJvNdyjktWD6leDpCmw==", 
    "ytSBHvzbEACq56aEHZlXEw==", "eV7WGimPD01weRI19ojO3g==", "vNkJyD9KOzOprGkYyfViMA==", 
    "r8jjZXWyax7JPfJUPFwRTQ==", "rJ1N3ONwDBK+jwFf+7xeHg==", "2xPbTqIww1KI/tVL2UH1cw==", 
    "1hk1AOU4DZXV52Auyr2FHA==", "aNH8uS5nrlwcHb8rLdZeXQ==", "5JPQs2z4N1Dru0dGI9ImBQ==", 
    "nbQIn5G4uyl8b1+A6aVkQg==", "A/UcwEccakKDuiATgoP1NA==", "JC57Ib2V7fOU/CgBk2R41g==", 
    "PsI8Ys++JveA+SuafbB8pg==", "eXiuBymYN+tcbjtpM9Vxmg==", "jEdP3Rs02d/4UE8G1GeE3A=="
    ), NULL, c("qjJf5iZtYboSPvqe1oa/xg==", "ul7kroLEB2cZx6AMGhjnrA==", 
    "OYRT/hYu1Dl3/S5WIWyLHA==", "HFiSH/Tu0RSaQgIbDEZfeA==", "gUBxBfxjGdyPNzqYX7t6nA==", 
    "m7UqzqaXUm1GkXMbxf+SJw==", "KjxvZwsVCNSTtXXKiidmjw==", "3UOqe+4qPVZYXvja8GBEqg==", 
    "a9Ba8b19tY/bprM7WA326A==", "uStr9Fg+JlU9B+hdBCafZg==", "i9J11W00HFmoeCDObOfSdA==", 
    "A9vOz8zSrwDiQcKv8hk64Q==", "/8QeMoqFwd/eJ+/6NKk1iQ==", "HbyJqQxUfH6oiW3skqPzGQ==", 
    "51H9RcZmdRgkgg4X6U/mhQ==", "dwat86ppe1b/WXSaGi8r3w==", "yBCbMedxtZdiGFXmTfk2eQ==", 
    "wKSIsw3sDPRQhLIhdQkBJw==", "3LkFUenHOXWL4Be5T4XmaQ==", "Krni6eGQUnZuL/jU0MzKNA==", 
    "Wt9BCH4guyC4oSIHwE8XGA==", "rbgxp/3YPdHiownOdZHf+A==", "34rmNRgT/xFDXIDwHKIY6Q==", 
    "pT3zFcGdlJKmR+khJLMoVw==", "eni3X9I2B4KRK+sho2MbjA==", "sxuba/1Brg4CrYL8AFv8ZQ==", 
    "EYIxPOXPVvop99YD0vjXPA==", "JC1xqrtmQEaohwzviYDFYA==", "qv+cfEEqsIGrDFuEqpkQuw==", 
    "d3xXMR1RDKZdrDwQd97kNQ==", "qU1JULumBTqw+m/rLr4E7A==", "teDCJvNdyjktWD6leDpCmw==", 
    "ytSBHvzbEACq56aEHZlXEw==", "eV7WGimPD01weRI19ojO3g==", "vNkJyD9KOzOprGkYyfViMA==", 
    "r8jjZXWyax7JPfJUPFwRTQ==", "rJ1N3ONwDBK+jwFf+7xeHg==", "2xPbTqIww1KI/tVL2UH1cw==", 
    "1hk1AOU4DZXV52Auyr2FHA==", "aNH8uS5nrlwcHb8rLdZeXQ==", "5JPQs2z4N1Dru0dGI9ImBQ==", 
    "nbQIn5G4uyl8b1+A6aVkQg==", "A/UcwEccakKDuiATgoP1NA==", "JC57Ib2V7fOU/CgBk2R41g==", 
    "PsI8Ys++JveA+SuafbB8pg==", "eXiuBymYN+tcbjtpM9Vxmg==", "jEdP3Rs02d/4UE8G1GeE3A=="
    )), user_data.contacts = list(list(), NULL, list(), NULL, 
    list())), row.names = c(NA, 5L), class = "data.frame")

Я хочу выполнить вычисление Jaccard, используя:

jaccard <- function(vector1, vector2) {

  return(length(intersect(vector1, vector2)) / 
           length(union(vector1, vector2)))

}

jaccardV <- Vectorize(jaccard)

и хочу немного очистить данные.

Я пытаюсь очистить строки списков длины NULL / NA / 0.

Пожалуйста, посоветуйте, как правильно сделать это, первое, о чем я подумал:

df %>% 
    dplyr::mutate(isNull = ifelse(is.null(unlist(user_data.contacts)), TRUE, FALSE))

Но везде возвращается False.

Есть ли способ сделать это правильно и эффективно?Пожалуйста, посоветуйте.

Наконец, после очистки я буду запускать:

df %>% 
  cleaning %>%
dplyr::mutate(contacts_jaccard = jaccardV(user_data.contacts, lag(user_data.contacts)))

Ответы [ 3 ]

0 голосов
/ 21 января 2019

Я думаю, это должно сработать для вас. Пройдите через столбец контактов, создайте новый столбец, который сообщает, является ли он пустым или нет, и затем отфильтруйте их на основе нового столбца

library(tidyverse)

new_df <- df %>%as_tibble() %>%
    mutate(is_Null = sapply(user_data.contacts, is_null)) %>%
    filter(is_Null == FALSE)

new_df
0 голосов
/ 21 января 2019

Столбец user_data.contacts является списком, когда вы изменяете этот столбец, он обрабатывает его как один список.Попробуйте сгруппировать данные rowwise до mutate.

library(dplyr)

df %>% 
  rowwise() %>% 
  mutate(isNull = is.null(unlist(user_data.contacts)))


# A tibble: 5 x 4 # added data to 1st observation for test
  keys.userId user_data.SSIDs user_data.contacts isNull
  <chr>       <list>          <list>             <lgl> 
1 9875        <chr [47]>      <list [3]>         FALSE 
2 5465        <NULL>          <NULL>             TRUE  
3 1234        <chr [47]>      <list [0]>         TRUE  
4 4567        <NULL>          <NULL>             TRUE  
5 8910        <chr [47]>      <list [0]>         TRUE
0 голосов
/ 21 января 2019

Это был бы способ сделать это:

library(dplyr)
library(purrr)
df %>% 
  filter(!map_lgl(user_data.contacts, is.null)) %>% 
  filter(!map_lgl(user_data.contacts, function(x) length(x) == 0)) %>% 
  filter(!map_lgl(user_data.contacts, is.na)) %>% 
  mutate(contacts_jaccard = jaccardV(user_data.contacts, lag(user_data.contacts)))

Это не приводит к выводу, поскольку в предоставленных вами макетных данных все строки теперь удалены. Нет необходимости создавать новый столбец isNull, если единственной целью является дальнейшее удаление строк. Я начал отдавать предпочтение map над sapply, поскольку добиться определенного результата действительно легко. В этом случае map_lgl будет давать только ИСТИНА / ЛОЖЬ.

Обратите внимание, что если один элемент столбца списка длиннее 1, вы должны использовать это вместо:

df %>% 
  filter(!map_lgl(user_data.contacts, is.null)) %>% 
  filter(!map_lgl(user_data.contacts, function(x) length(x) == 0)) %>% 
  filter(!map_lgl(user_data.contacts, function(x) is.na(x)[1])) %>% 
  mutate(contacts_jaccard = jaccardV(user_data.contacts, lag(user_data.contacts)))
...