仅选择数字列进行替换

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) &lt;- 不这样做 @MobeusZoom 对不起,我不明白。为什么不dplyrFilter(is.numeric,df) &lt;- 将不起作用,因为没有像 Filter&lt;- 这样的方法。 Filter 不是Filter&lt;- 的函数。两者有区别。 那么为什么它不起作用呢?我以为Filter 会在数据框df 上操作,只选择数字列;然后这些将被来自右侧的任何内容所取代。但它不会那样发生。但如果你写了iris[,1:4] &lt;-,那当然可以 因为没有为Filter 定义&lt;- 方法。你不能使用没有定义的东西。 iris[,1:4] &lt;- 有效,因为 [&lt;- 已定义。检查?`[&lt;-`【参考方案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)

【讨论】:

以上是关于仅选择数字列进行替换的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server:出于数学目的,如何仅选择带有度量单位的数字[重复]

R:如何只选择连续的数字列

选择性排序

如何查找仅包含数字数据的非数字列?

允许在长度受限的字段中替换数字

excel如何查找重复的数据,并分别替换