Можно ли удалить несколько строк в .x из purrr ::: iwalk? - PullRequest
1 голос
/ 10 мая 2019

Я использую purrr ::: iwalk вот так, но он не делает то, что я хочу:

purrr:::iwalk(DGE_tables, ~ .x[-which(.x$column1 %in% VectorOfSpecificValues),])

DGE_tables - это список фреймов данных.В этом все кадры данных я хочу удалить строки, которые имеют определенные значения в column1.Фреймы данных имеют одинаковую структуру.

Возможно ли это сделать с purrr ::: iwalk ?Или есть лучший способ сделать это?

РЕДАКТИРОВАТЬ : Пример:

Список данных:

DGE_tables
# Display
$dataframe1
    column1   column2
1   to_delete    56
2   to_keep      45

$dataframe2
    column1   column2
1   to_delete    78
2   to_keep      27

...

Поэтому я хочу удалить строки, которые имеют $ column1 = "to_delete".Как это:

# wanted result
$dataframe1
    column1   column2
1   to_keep      45

$dataframe2
    column1   column2
1   to_keep      27

...

Ответы [ 3 ]

3 голосов
/ 10 мая 2019

purrr имеет keep() и discard() только для такого рода вещей:

library(purrr)

l <- list(
    list(col1 = 'to keep', col2 = 1),
    list(col1 = 'to discard', col2 = 2)
)

purrr::keep(l, ~ .x[['col1']] == 'to keep')
#> [[1]]
#> [[1]]$col1
#> [1] "to keep"
#> 
#> [[1]]$col2
#> [1] 1
purrr::discard(l, ~ .x[['col1']] == 'to discard')
#> [[1]]
#> [[1]]$col1
#> [1] "to keep"
#> 
#> [[1]]$col2
#> [1] 1
2 голосов
/ 10 мая 2019

Здесь работают несколько вещей. Поскольку у меня нет ваших данных (пока?), Я сделаю свои собственные, довольно грубо:

dge <- list(mtcars[1:5,], mtcars[1:5,])

Некоторые проблемы:

  1. По определению purrr::walk и purrr::iwalk возвращают исходный кадр .x, независимо от того, что вы делаете в функциональном блоке . Как пример, посмотрите это:

    (purrr::iwalk(dge, ~ return(NULL)))
    # [[1]]
    #                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
    # Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
    # Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
    # Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
    # Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
    # Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
    # [[2]]
    #                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
    # Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
    # Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
    # Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
    # Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
    # Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
    

    (Если вы просто сделаете purrr::iwalk(dge, ...) без окружающих паренов, вы ничего не увидите, потому что по умолчанию возвращается возвращаемое значение невидимо . Парены заставляют его быть видимым.)

    Таким образом, сложный момент заключается в том, что ваш пример простой фильтрации в iwalk не будет работать. Для этого вы, вероятно, хотите purrr::imap. (Если вы делаете больше и маленький пример в вашем вопросе был более коротким фрагментом кода, то вы, вероятно, все еще хорошо справляетесь с iwalk.)

  2. Я предпочитаю , а не использовать which в подобных блоках, так как отсутствие с отрицанием which может быть проблематичным (отрицательный пустой вектор не делает "ничего" ). Вместо этого я предлагаю использовать логические векторы, а не целочисленные векторы.

    Примеры: я попробую глупое условие 1 %in% 2, которое, очевидно, ничего не должно найти (и с вашим отрицанием вернет все строки):

    dge[[1]][ -which(1 %in% 2), ]
    #  [1] mpg  cyl  disp hp   drat wt   qsec vs   am   gear carb
    # <0 rows> (or 0-length row.names)
    

    Использование логического вектора вместо (и ! вместо -) возвращает то, что мы ожидаем (т.е. все строки):

    dge[[1]][ !(1 %in% 2), ]
    #                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
    # Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
    # Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
    # Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
    # Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
    # Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
    
1 голос
/ 10 мая 2019

Один из вариантов будет filter

library(tidyverse)
map(DGE_tables, ~ .x %>% 
                  filter(column1 != "to_delete"))
#[[1]]
#  column1 column2
#1 to_keep      45

#[[2]]
#  column1 column2
#1 to_keep      27

Или с slice

map(DGE_tables, ~ .x %>% 
                  slice(which(column1 != "to_delete")))

Или это также можно сделать с помощью base R

lapply(DGE_tables, subset, subset = column1 != "to_delete")

ПРИМЕЧАНИЕ. Набор данных OP имеет значение list из data.frame и нуждается в возвращаемом выходе list из data.frame с с подмножеством строк

и не будет работать с keep или discard

purrr::keep(DGE_tables, ~ .x[['column1']] == 'to keep')

Ошибка: функции предиката должны возвращать один TRUE или FALSE, а не логический вектор длины 2

данные

DGE_tables <- list(structure(list(column1 = c("to_delete", "to_keep"), 
   column2 = c(56L, 
45L)), class = "data.frame", row.names = c("1", "2")), structure(list(
    column1 = c("to_delete", "to_keep"), column2 = c(78L, 27L
    )), class = "data.frame", row.names = c("1", "2")))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...