有条件地删除每列的值,但使用循环将每列保留为新数据框
Conditionally remove value for each column but keep each column as a new dataframe using a loop
我有以下简化的数据框。
test <- data.frame(
ice = c(1, 0.8, 0.5, 0.4),
eonia = c(0.5, 0, 0, -0.4),
euribor = c(1, -0.8, 1, -0.2),
cp = c(-0.7, -0.6, -0.4, -0.5)
)
row.names(test) <- colnames(test)
我想为每一列应用一个条件,它只保留那些满足条件的值:
test[(test$ice>= 0.8 & test$ice< 1) | (test$ice<= -0.8 & test$ice> -1), , drop=FALSE]
但是,我的真实数据框包含许多变量,我不想将此代码“手动”应用到每一列。
请注意,在针对此条件进行过滤后,我可能需要将每一列添加到列表或新数据框中。
是否有一种有效的方法来遍历每一列,并可能将每一列安全地作为新数据框或将其添加到列表中。
第一个数据框(或列表的一部分)应如下所示:
ice
ice 1
eonia 0.8
非常感谢
我们可以定义自定义函数并循环遍历列。在这里,我使用的 dplyr::between
等同于 x >= left & x <= right
但它可以很容易地修改为您需要的代码。
custom_filter <- function(df, colName, right, left, right_n = -right, left_n = -left){
require(dplyr)
require(rlang)
df %>%
filter(between(!! sym(colName), right, left) | between(!! sym(colName), right_n, left_n))
}
lapply(names(test) , function(colN) custom_filter(test, colN, 0.8, 1))
使用您的选择逻辑创建一个 f
函数,然后遍历数据中的每一列并使用以下函数对其进行子集化:
f <- function(x) (x >= 0.8 & x < 1) | (x <= -0.8 & x > -1)
lapply(names(test), \(n) test[ f(test[[n]]), n, drop=FALSE] )
如果函数需要接受 0 两侧的低点和高点参数,也可以在其中进行编辑:
f <- function(x, low, high) abs(x) >= low & abs(x) < high
lapply(names(test), \(n) test[ f(test[[n]], 0.8, 1.0), n, drop=FALSE] )
#[[1]]
# ice
#eonia 0.8
#
#[[2]]
#[1] eonia
#<0 rows> (or 0-length row.names)
#
#[[3]]
# euribor
#eonia -0.8
#
#[[4]]
#[1] cp
#<0 rows> (or 0-length row.names)
[]
中的条件已应用于每一列。为了在丢失值的情况下保持矩阵布局,您可以显式添加例如NA
.
这是一个例子(在@thelatemail 的帮助下编辑):
test[ !(( test >= 0.8 & test < 1 )|( test <= -0.8 & test > -1)) ] <- NA
ice eonia euribor cp
ice NA NA NA NA
eonia 0.8 NA -0.8 NA
euribor NA NA NA NA
cp NA NA NA NA
请记住,这是所谓的就地修改,直接更改您的数据集(此处为数据框 test
)。
我有以下简化的数据框。
test <- data.frame(
ice = c(1, 0.8, 0.5, 0.4),
eonia = c(0.5, 0, 0, -0.4),
euribor = c(1, -0.8, 1, -0.2),
cp = c(-0.7, -0.6, -0.4, -0.5)
)
row.names(test) <- colnames(test)
我想为每一列应用一个条件,它只保留那些满足条件的值:
test[(test$ice>= 0.8 & test$ice< 1) | (test$ice<= -0.8 & test$ice> -1), , drop=FALSE]
但是,我的真实数据框包含许多变量,我不想将此代码“手动”应用到每一列。 请注意,在针对此条件进行过滤后,我可能需要将每一列添加到列表或新数据框中。
是否有一种有效的方法来遍历每一列,并可能将每一列安全地作为新数据框或将其添加到列表中。
第一个数据框(或列表的一部分)应如下所示:
ice
ice 1
eonia 0.8
非常感谢
我们可以定义自定义函数并循环遍历列。在这里,我使用的 dplyr::between
等同于 x >= left & x <= right
但它可以很容易地修改为您需要的代码。
custom_filter <- function(df, colName, right, left, right_n = -right, left_n = -left){
require(dplyr)
require(rlang)
df %>%
filter(between(!! sym(colName), right, left) | between(!! sym(colName), right_n, left_n))
}
lapply(names(test) , function(colN) custom_filter(test, colN, 0.8, 1))
使用您的选择逻辑创建一个 f
函数,然后遍历数据中的每一列并使用以下函数对其进行子集化:
f <- function(x) (x >= 0.8 & x < 1) | (x <= -0.8 & x > -1)
lapply(names(test), \(n) test[ f(test[[n]]), n, drop=FALSE] )
如果函数需要接受 0 两侧的低点和高点参数,也可以在其中进行编辑:
f <- function(x, low, high) abs(x) >= low & abs(x) < high
lapply(names(test), \(n) test[ f(test[[n]], 0.8, 1.0), n, drop=FALSE] )
#[[1]]
# ice
#eonia 0.8
#
#[[2]]
#[1] eonia
#<0 rows> (or 0-length row.names)
#
#[[3]]
# euribor
#eonia -0.8
#
#[[4]]
#[1] cp
#<0 rows> (or 0-length row.names)
[]
中的条件已应用于每一列。为了在丢失值的情况下保持矩阵布局,您可以显式添加例如NA
.
这是一个例子(在@thelatemail 的帮助下编辑):
test[ !(( test >= 0.8 & test < 1 )|( test <= -0.8 & test > -1)) ] <- NA
ice eonia euribor cp
ice NA NA NA NA
eonia 0.8 NA -0.8 NA
euribor NA NA NA NA
cp NA NA NA NA
请记住,这是所谓的就地修改,直接更改您的数据集(此处为数据框 test
)。