Фильтрация строк по нескольким столбцам в R - PullRequest
0 голосов
/ 07 мая 2020

У меня есть таблица с одиннадцатью столбцами, и я хотел бы отфильтровать в десяти столбцах (PC1: PC10) строки, которые не равны 145.

Я попытался решить эту проблему с помощью a for l oop. Однако это не работает. Есть ли другой вариант или кто-нибудь может мне объяснить, в чем моя ошибка? Я тоже пробовал с lapply, но не знаю, как интегрировать функцию фильтра. Большое спасибо.

install.packages("tidyverse")
library(tidyverse) 

set.seed(120)

data.matrix <- matrix(nrow=100, ncol=10)
colnames(data.matrix) <- c(
  paste("PC", 1:10, sep=""))
rownames(data.matrix) <- paste("food", 1:100, sep="")
for (i in 1:100) {
  wt.values <- rpois(10, lambda=sample(x=10:1000, size=1))

  data.matrix[i,] <- c(wt.values)
}
head(data.matrix)
#>       PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10
#> food1 145 150 136 147 134 158 152 141 152  115
#> food2 629 615 592 636 617 595 618 602 621  626
#> food3 343 355 401 378 361 393 365 374 352  371
#> food4 420 433 417 394 431 430 458 453 404  459
#> food5 866 850 885 826 845 781 838 835 850  857
#> food6  10   7   7  11   7   4   8  11   9   12
dim(data.matrix)
#> [1] 100  10


data <- data.matrix %>% data.frame() %>%  rownames_to_column(var = "food_groups") %>% as_tibble()


# Normally I would do: 

data %>%  filter(!PC1 == 145 ) %>% select(PC1)
data %>%  filter(!PC2 == 145 ) %>% select(PC2)
data %>%  filter(!PC3 == 145 ) %>% select(PC3)

# However, I would like to avoid repetition by looping (or lapply...)

# I tried this and it does not work:

fltr <- function(y) {
  f <- filter(!y == 145) 
  f
}

loadings_final <- function(x) {
  nc <- ncol(x)
  filters <- numeric(nc)
  for (i in 1:nc) {
    filters[i] <- fltr(x[,i])
  }
  filters
}

loadings_final(data)
#> Error in UseMethod("filter_"): nicht anwendbare Methode für 'filter_' auf Objekt der Klasse "c('matrix', 'logical')" angewendet

Создано 07.05.2020 с помощью пакета REPEX (v0.3.0)

Ответы [ 2 ]

2 голосов
/ 07 мая 2020

Вы можете получить список значений, используя lapply:

list_output <- lapply(data[-1], function(x) data.frame(col = x[x != 145]))

Это также можно сделать с помощью map

list_output <- purrr::map(data[-1], ~tibble(col = .x[.x != 145]))
1 голос
/ 07 мая 2020
library(reshape2)
data %>% 
melt(., id.vars = "food_groups", measure_vars=c('PC1','PC2','PC3','PC4','PC5','PC6','PC7','PC8','PC9','PC10')) %>% 
filter(value != 375) 

возвращает:

    food_groups variable value
1         food2      PC1    92
2         food3      PC1   801
3         food4      PC1   398
4         food5      PC1   238
5         food6      PC1   213
6         food7      PC1   281
7         food8      PC1  1031 ....

Вы заметили, что комбинация PC1-food1 отфильтрована.

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

library(reshape2)
data %>% 
melt(., id.vars = "food_groups", measure_vars=c('PC1','PC2','PC3','PC4','PC5','PC6','PC7','PC8','PC9','PC10')) %>% 
filter(value != 375) %>% 
group_split(variable) -> mylist

После этого:

# name list elements
names(mylist) <- c('PC1','PC2','PC3','PC4','PC5','PC6','PC7','PC8','PC9','PC10')
# assign to global environment
list2env(mylist,globalenv())

# now you have: 
> ls()
 [1] "data"        "data.matrix" "i"           "mylist"      "PC1"
 [6] "PC10"        "PC2"         "PC3"         "PC4"         "PC5"
[11] "PC6"         "PC7"         "PC8"         "PC9"         "wt.values"

Изменить: Ответ @Ronak Shah ниже представлен единый подход для создания списка таблиц, разделенных в соответствии с P C. После выполнения его единственной строки вам нужно только позвонить list2env(), чтобы получить желаемый результат. Если кому-то нравится краткость, предпочтительнее его ответ.

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