仅选择数字列进行替换
Posted
技术标签:
【中文标题】仅选择数字列进行替换【英文标题】:Selecting only numeric columns for replacement 【发布时间】:2020-09-25 11:49:07 【问题描述】:我有一个包含一些数字、一些整数和一些因子列的数据框。我正在尝试将数据框转换为仅对数字列进行平方,但 this thread 中的解决方案在此用例中不起作用:
square <- function(x)return(x^2)
Numerics <- function(df)return(Filter(is.numeric,df))
SquareD <- function(df)
Numerics(df) <- apply(Numerics(df),2,square)
return(df)
现在,在尝试运行 SquareD(iris)
时,我得到“Numerics(df)
我怎样才能让它工作?类似的东西
iris[sapply(df,is.numeric)] <- apply(iris[sapply(iris,is.numeric)],2,square)
确实有效,但它又长又笨重。我宁愿做一些简短的事情(包含在一个函数中),而我可以重复。但是
Numerics <- function(df)return(df[sapply(df,is.numeric)])
SquareD <- function(df)
Numerics(df) <- apply(Numerics(df),2,square)
return(df)
还是不行。不使用新定义的函数,但仍然有点短的东西,比如
SquareD <- function(df)
Filter(is.numeric,df) <- apply(Filter(is.numeric,df),2,square)
return(df)
也不行。 (或例如dplyr::select_if(df,is.numeric)
代替上面的Filter(is.numeric,df)
)
注意:我想如上所示执行此操作,即使用一种既适用于替换又适用于选择的方法(因此我尝试使用该线程中建议的选择方法)并且很短而无需重写有点冗长的代码(就像 sapply 一样)。例如,我可能想用 iris 数值列的平方值替换 ANOTHER 数据集的数值列。那种应用。
我知道单独替换我可以使用 dplyr::mutate_if 但我不希望那样。而是希望了解为什么选择方法在这里不起作用,并且可以对其进行调整。如上所述,我还想在一行中执行此操作(或使用最终在一行中执行的预定义函数)。最后,除了 dplyr,没有库。
【问题讨论】:
【参考方案1】:如果你想在基础 R 中这样做,你可以使用:
SquareD <- function(df)
cols <- sapply(df, is.numeric)
df[cols] <- lapply(df[cols], square)
return(df)
SquareD(iris)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#1 26 12.2 2.0 0.04 setosa
#2 24 9.0 2.0 0.04 setosa
#3 22 10.2 1.7 0.04 setosa
#4 21 9.6 2.2 0.04 setosa
#5 25 13.0 2.0 0.04 setosa
#6 29 15.2 2.9 0.16 setosa
#....
在dplyr
,
library(dplyr)
iris %>% mutate(across(where(is.numeric), square))
或者在旧版本中:
iris %>% mutate_if(is.numeric, square)
【讨论】:
正如我所说,我想在一行中完成它,或者在一行中使用可执行的函数(所以不是你的基本解决方案),并且使用一种适用于选择/子集以及替换(所以不是你的 dplyr)。或者理解为什么这是不可能的。我正在寻找的基本上是写iris[,1:4]
的替代品,它适用于任何数字列。这就是为什么我不明白为什么Filter(is.numeric,df) <-
不这样做
@MobeusZoom 对不起,我不明白。为什么不dplyr
? Filter(is.numeric,df) <-
将不起作用,因为没有像 Filter<-
这样的方法。
Filter
不是Filter<-
的函数。两者有区别。
那么为什么它不起作用呢?我以为Filter
会在数据框df
上操作,只选择数字列;然后这些将被来自右侧的任何内容所取代。但它不会那样发生。但如果你写了iris[,1:4] <-
,那当然可以
因为没有为Filter
定义<-
方法。你不能使用没有定义的东西。 iris[,1:4] <-
有效,因为 [<-
已定义。检查?`[<-`
【参考方案2】:
应用于data.frame:
iris_sqrd <- data.frame(Map(function(x) x**2, iris[,sapply(iris, is.numeric)]))
作为一个函数:
# Function:
square_df <- function(df)data.frame(Map(function(x) x**2, df[,sapply(df, is.numeric)]))
# Application:
iris_sqrd <- square_df(iris)
【讨论】:
以上是关于仅选择数字列进行替换的主要内容,如果未能解决你的问题,请参考以下文章