{R} 使用 purr 删除空白或唯一列
{R} Remove blank or unique columns using purr
我最近发现了 purrr,我非常喜欢地图功能。有谁知道如何解决以下问题:
我有一个数据框,我根据某个变量将其拆分为多个数据框 - 拆分后,我想删除结果列表中数据框中唯一的列。在单个数据框中解决此问题非常容易,但在列表中我不太确定 - 您将如何使用 map 解决此问题?
我目前的解决方案如下:
set.seed(123)
dat <- data.frame(target = round(runif(9, min = 0, max = 1), 0),
split_var = c(rep("x", 3), rep("y", 3), rep("z", 3)),
var1 = c(rep("a", 3), rep("b", 2), "c", rep("d", 2), "e"),
var2 = paste("m", round(rnorm(9, mean = 5), 2), sep = "_"))
mod_dat <- dat %>% split(dat$split_var)
remover <- function(df){
non_unique_cols <- sapply(df, function(x) length(unique(x))) > 1
return(df[, non_unique_cols])
}
map(mod_dat, remover)
还有一个问题,我不希望 map
将 remover
应用于 target
变量。
任何人都可以使用 purrr 包中的地图来帮助完成这项工作。
已解决
@akrun 提供的最终解决方案 - 完全归功于他。
mod_dat <- dat %>%
split(.$split_var) %>%
map( ~ Filter(function(x) n_distinct(x) > 1, .)) %>%
Filter(function(x) sum(names(x) %in% "target"), .)
mod_dat
略有不同的是,在这里我们还删除了删除目标变量的数据帧 - 出于我的目的,保留这些数据帧并不是必需的。以下代码可用于快速确定保留哪些级别,删除哪些级别。
# In
unique(dat$split_var)[(unique(dat$split_var) %in% names(mod_dat))]
# Out
unique(dat$split_var)[!(unique(dat$split_var) %in% names(mod_dat))]
我们可以试试
library(dplyr)
library(purrr)
dat %>%
split(.$split_var) %>%
map(~Filter(function(x) n_distinct(x) >1 , .))
根据 OP 的数据集和更新后的问题,我们可以仅使用 setdiff
到 select Filter
所需的列,而使用 bind_cols
,我们可以加入'target'
dat %>%
split(.$split_var) %>%
map(~bind_cols(.["target"], Filter(function(x)
n_distinct(x) >1 , .[setdiff(names(.), "target")])))
#$x
# target var2
#1 0 m_4.89
#2 1 m_4.88
#3 0 m_5.18
#$y
# target var1 var2
#1 1 b m_6.28
#2 1 b m_3.27
#3 0 c m_6.69
#$z
# target var1 var2
#1 1 d m_5.5
#2 1 d m_7.53
#3 1 e m_5.55
数据
dat <- data.frame(v1 = c(rep(1, 3), 4:10), split_var = rep(LETTERS[1:3],
c(3, 3, 4)), stringsAsFactors=FALSE)
我最近发现了 purrr,我非常喜欢地图功能。有谁知道如何解决以下问题:
我有一个数据框,我根据某个变量将其拆分为多个数据框 - 拆分后,我想删除结果列表中数据框中唯一的列。在单个数据框中解决此问题非常容易,但在列表中我不太确定 - 您将如何使用 map 解决此问题?
我目前的解决方案如下:
set.seed(123)
dat <- data.frame(target = round(runif(9, min = 0, max = 1), 0),
split_var = c(rep("x", 3), rep("y", 3), rep("z", 3)),
var1 = c(rep("a", 3), rep("b", 2), "c", rep("d", 2), "e"),
var2 = paste("m", round(rnorm(9, mean = 5), 2), sep = "_"))
mod_dat <- dat %>% split(dat$split_var)
remover <- function(df){
non_unique_cols <- sapply(df, function(x) length(unique(x))) > 1
return(df[, non_unique_cols])
}
map(mod_dat, remover)
还有一个问题,我不希望 map
将 remover
应用于 target
变量。
任何人都可以使用 purrr 包中的地图来帮助完成这项工作。
已解决
@akrun 提供的最终解决方案 - 完全归功于他。
mod_dat <- dat %>%
split(.$split_var) %>%
map( ~ Filter(function(x) n_distinct(x) > 1, .)) %>%
Filter(function(x) sum(names(x) %in% "target"), .)
mod_dat
略有不同的是,在这里我们还删除了删除目标变量的数据帧 - 出于我的目的,保留这些数据帧并不是必需的。以下代码可用于快速确定保留哪些级别,删除哪些级别。
# In
unique(dat$split_var)[(unique(dat$split_var) %in% names(mod_dat))]
# Out
unique(dat$split_var)[!(unique(dat$split_var) %in% names(mod_dat))]
我们可以试试
library(dplyr)
library(purrr)
dat %>%
split(.$split_var) %>%
map(~Filter(function(x) n_distinct(x) >1 , .))
根据 OP 的数据集和更新后的问题,我们可以仅使用 setdiff
到 select Filter
所需的列,而使用 bind_cols
,我们可以加入'target'
dat %>%
split(.$split_var) %>%
map(~bind_cols(.["target"], Filter(function(x)
n_distinct(x) >1 , .[setdiff(names(.), "target")])))
#$x
# target var2
#1 0 m_4.89
#2 1 m_4.88
#3 0 m_5.18
#$y
# target var1 var2
#1 1 b m_6.28
#2 1 b m_3.27
#3 0 c m_6.69
#$z
# target var1 var2
#1 1 d m_5.5
#2 1 d m_7.53
#3 1 e m_5.55
数据
dat <- data.frame(v1 = c(rep(1, 3), 4:10), split_var = rep(LETTERS[1:3],
c(3, 3, 4)), stringsAsFactors=FALSE)