#r #subset
#r #подмножество
Вопрос:
У меня есть набор данных с именем DF1, который выглядит следующим образом:
V1 V2 V3 V4 V5 V6
A01N A01N A01P Null Null Null
C09K A61K C09D C08K Null Null
A61K A61P A61P A61K A61K A61K
A01D A01D A01D A01D A01D Null
E06A Null Null Null Null Null
также вектор с именем V:
(A01N C09K A01D)
Я хочу, чтобы подмножество DF1 основывалось на элементах вектора, если одна строка в DF1 содержит элементы в V, независимо от того, в каком столбце, тогда сохраните строку. если нет, отбросьте его. Результат должен быть:
V1 V2 V3 V4 V5 V6
A01N A01N A01P Null Null Null
C09K A61K C09D C08K Null Null
Я пытаюсь использовать subset(): test_t1 <- subset(DF1, DF1[,1:6] %в% V)
но я просто знаю, как подмножество одного столбца или строки, как обрабатывать несколько столбцов?
Ответ №1:
Попробуйте reshaping
использовать tidyverse
функции. Вы форматируете столбцы в long, чтобы затем сравнить их с вектором значений. После этого выполните фильтрацию, а затем измените ее на wide. Вот код:
library(tidyverse)
#Data
vec <- c('A01N','C09K','A01D')
#Code
new <- df %>% mutate(id=row_number()) %>%
pivot_longer(-id) %>%
mutate(Flag= (value%in%vec)) %>%
group_by(id) %>%
mutate(Sum=sum(Flag)) %>%
filter(Sum>=1) %>%
select(-c(Flag,Sum)) %>%
pivot_wider(names_from = name,values_from=value) %>%
ungroup %>% select(-id)
Вывод:
# A tibble: 3 x 6
V1 V2 V3 V4 V5 V6
<chr> <chr> <chr> <chr> <chr> <chr>
1 A01N A01N A01P Null Null Null
2 C09K A61K C09D C08K Null Null
3 A01D A01D A01D A01D A01D Null
Или использовать base R
с apply()
:
#Code2
new <- df[apply(df,1,function(x) ifelse(sum(x %in% vec)>=1,1,0))==1,]
Вывод:
V1 V2 V3 V4 V5 V6
1 A01N A01N A01P Null Null Null
2 C09K A61K C09D C08K Null Null
4 A01D A01D A01D A01D A01D Null
Некоторые используемые данные:
#Data
df <- structure(list(V1 = c("A01N", "C09K", "A61K", "A01D", "E06A"),
V2 = c("A01N", "A61K", "A61P", "A01D", "Null"), V3 = c("A01P",
"C09D", "A61P", "A01D", "Null"), V4 = c("Null", "C08K", "A61K",
"A01D", "Null"), V5 = c("Null", "Null", "A61K", "A01D", "Null"
), V6 = c("Null", "Null", "A61K", "Null", "Null")), class = "data.frame", row.names = c(NA,
-5L))
Если слишком много переменных создают проблемы, вот более упрощенная версия кода (большое спасибо GregorThomas):
#Code1
new <- df %>% mutate(id=row_number()) %>%
pivot_longer(-id) %>%
group_by(id) %>%
filter(sum(value %in% vec) > 0) %>%
pivot_wider(names_from = name,values_from=value) %>%
ungroup %>% select(-id)
#Code2
new <- df[apply(df,1,function(x) sum(x %in% vec)>=1),]
Комментарии:
1. Если вы не возражаете против общего замечания, вы … склонны делать много дополнительных шагов. Я думаю
mutate(Flag= (value%in%vec)) %>% group_by(id) %>% mutate(Sum=sum(Flag)) %>% filter(Sum>=1) %>% select(-c(Flag,Sum))
, можно было бы сократить доgroup_by(id) %>% filter(sum(value %in% vec) > 0))
.2. Аналогично в вашей базовой версии, =
ifelse(sum(x %in% vec)>=1,1,0))==1
— это долгий путь для записиsum(x %in% vec) >= 1
. Вы получаете желаемый логический результат, затем преобразуете его в числовой сifelse()
помощью , а затем преобразуете обратно в логический с== 1
помощью . Пропустите преобразования.3. @GregorThomas Отличные предложения, позвольте мне добавить в код, который я использую, чтобы сделать больше шагов для отслеживания того, что происходит!
4. Я согласен, что временные переменные (особенно с красивыми именами, которые у вас есть) могут быть полезны в сложных процессах. Особенно, если они необходимы для более чем одного использования. Но в данном случае все довольно просто, и я думаю, что создание столбцов для использования один раз, а затем удаление делает решение менее понятным, а не более понятным.
Ответ №2:
Это простая однострочная строка в базе R:
DF1[rowSums(DF1 %in% vec) > 0, ]
Ответ №3:
Опция в base R
может быть
subset(DF1, Reduce(` `, lapply(DF1, `%in%`, vec)) > 0)
-вывод
# V1 V2 V3 V4 V5 V6
#1 A01N A01N A01P Null Null Null
#2 C09K A61K C09D C08K Null Null
#4 A01D A01D A01D A01D A01D Null
данные
DF1 <- structure(list(V1 = c("A01N", "C09K", "A61K", "A01D", "E06A"),
V2 = c("A01N", "A61K", "A61P", "A01D", "Null"), V3 = c("A01P",
"C09D", "A61P", "A01D", "Null"), V4 = c("Null", "C08K", "A61K",
"A01D", "Null"), V5 = c("Null", "Null", "A61K", "A01D", "Null"
), V6 = c("Null", "Null", "A61K", "Null", "Null")),
class = "data.frame", row.names = c(NA,
-5L))
vec <- c('A01N','C09K','A01D')