Передача столбцов в «with» в lapply - PullRequest
0 голосов
/ 25 апреля 2018

Как передать столбцы данных в функцию with при вызове lapply?

Я пробовал это, и они не работают!

lapply(data[ , grepl( "Measured." , names( data ) ) ], with, (. <= 5 & . >= 1) | . == 4244)

lapply(data[ , grepl( "Measured." , names( data ) ) ], function(x) with((x <= 5 & x >= 1) | x == 4244))

Iя пытаюсь увидеть, находятся ли значения в столбцах Measured. между 1 и 5, и, кроме того, также принимается 4244.

Пример набора данных:

data <- structure(list(ID = 1:10, Date = c(2018L, 2018L, 2018L, 2015L, 
2018L, 2015L, 2015L, 2014L, 2014L, 2014L), Gender = structure(c(2L, 
2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L), .Label = c("F", "M"), class = "factor"), 
    Measured.1 = c(1L, 7L, 1L, 6L, 6L, 2L, 5L, 4L, 2L, 6L), Measured.2 = c(9L, 
    2L, 4L, 5L, 2L, 3L, 6L, 3L, 7L, 7L), Measured.3 = c(9L, 4L, 
    35L, 3L, 4L, 2L, 2L, 1L, 3L, 4L), Measured.4 = c(12L, 8L, 
    50L, 7L, 2L, 6L, 2L, 2L, 1L, 2L), Text = structure(c(1L, 
    1L, 1L, 1L, 1L, 2L, 2L, 2L, 1L, 1L), .Label = c("N", "Y"), class = "factor"), 
    Test = c(5L, 5L, 5L, 5L, 5L, 6L, 6L, 6L, 6L, 6L)), .Names = c("ID", 
"Date", "Gender", "Measured.1", "Measured.2", "Measured.3", "Measured.4", 
"Text", "Test"), class = "data.frame", row.names = c(NA, -10L
))

И еговывод:

   ID Date Gender Measured.1 Measured.2 Measured.3 Measured.4 Text Test
1   1 2018      M          1          9          9         12    N    5
2   2 2018      M          7          2          4          8    N    5
3   3 2018      M          1          4         35         50    N    5
4   4 2015      M          6          5          3          7    N    5
5   5 2018      M          6          2          4          2    N    5
6   6 2015      M          2          3          2          6    Y    6
7   7 2015      F          5          6          2          2    Y    6
8   8 2014      F          4          3          1          2    Y    6
9   9 2014      F          2          7          3          1    N    6
10 10 2014      F          6          7          4          2    N    6

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

Используя базу R, вы можете извлечь строки, соответствующие этим критериям:

data[data[,1][data[,4] >= 1 & data[,4] <= 5 & data[,5] >= 1 & data[,5] <= 5 & data[,6] >= 1 & data[,6] <= 5 & data[,7] >= 1 & data[,7] <= 5 | data[,4] == 4244 | data[,5] == 4244 | data[,6] == 4244 | data[,7] == 4244],]

Я использую & для создания аддитивных критериев (вы ищете строки, где измерены 1, измеренное.*

  ID Date Gender Measured.1 Measured.2 Measured.3 Measured.4 Text Test
8  8 2014      F          4          3          1          2    Y    6

Это не самый красивый фрагмент кода, но (согласно микробенчмарку) он работает в 43 раза быстрее, чем подход dplyr от января.

0 голосов
/ 25 апреля 2018

Помимо базового R вы можете использовать dplyr решение:

library(dplyr)
data %>%
  filter_at(vars(starts_with("Measured")), 
            any_vars((. >= 1 & . <= 5) | . == 4244))

Это будет искать записи, в которых по крайней мере один из столбцов Measured имеетзначение от 1 до 5 или 4244.
Если вы хотите быть ограничительным, и все значения должны находиться в этом диапазоне, вы можете изменить его на:

data %>%
  filter_at(vars(starts_with("Measured")), 
            all_vars((. >= 1 & . <= 5) | . == 4244))


Первый производит
   ID Date Gender Measured.1 Measured.2 Measured.3 Measured.4 Text Test
1   1 2018      M          1          9          9         12    N    5
2   2 2018      M          7          2          4          8    N    5
3   3 2018      M          1          4         35         50    N    5
4   4 2015      M          6          5          3          7    N    5
5   5 2018      M          6          2          4          2    N    5
6   6 2015      M          2          3          2          6    Y    6
7   7 2015      F          5          6          2          2    Y    6
8   8 2014      F          4          3          1          2    Y    6
9   9 2014      F          2          7          3          1    N    6
10 10 2014      F          6          7          4          2    N    6

В то время как последний дает

  ID Date Gender Measured.1 Measured.2 Measured.3 Measured.4 Text Test
1  8 2014      F          4          3          1          2    Y    6


То же самое можно сделать гораздо более быстрым (но менее читаемым) способом с основанием R: Вы можете использовать базовый R подход с масками и apply:
# set up the cols of interest
colmask <- grepl("^Measured", names(data))

# apply the function rowwise (=1)
rowmask <- apply(data[colmask], 1, function(col) {
  any(((col >= 1 & col <= 5) | col == 4244))
})
data[rowmask,]

или

colmask <- grepl("^Measured", names(data))
rowmask <- apply(data[colmask], 1, function(col) {
  all(((col >= 1 & col <= 5) | col == 4244))
})
data[rowmask,]

Очевидно, это дает те же результаты.

...