如果最大值超过特定限制,则将列除以 1000
Divide column by 1000 if maximum exceed certain limit
我想编写一个非常简单的程序:它应该遍历数据框中的所有列,如果至少有一个观察值大于 1000,那么程序应该将该变量除以 1000,然后将 "in (000)"
添加到变量名。
我的解决方案
set.seed(42)
df <- data.frame("Norm" = rnorm(100, 1000, 0.1), rexp(100))
for (var in seq_len(ncol(df))) {
if (max(df[, var], na.rm = T) > 1000) {
df[, var] <- df[, var] / 1000
colnames(df)[var] <- print(paste(colnames(df[var]), "(in 000')"))
}
}
不过我觉得有点不方便。我认为这里不需要循环。我试着用应用来做,但我不确定为什么我得到的是除以 1000 的列的最大值,而不是每个值除以 1000 的数据框:
apply(df, 2, function(x) ifelse(max(x) > 1000, x/1000, x))
Norm rexp.100.
0.9999925 0.4473922
你知道如何不用循环来完成吗?
ab1k <- sapply(df, function(x) any(x > 1000))
df[ab1k] <- df[ab1k]/1000
names(df)[ab1k] <- paste(names(df)[ab1k], "(in 000')")
apply
用于矩阵,不要在数据帧上使用它。 ifelse
用于矢量测试 - 输出与输入的形状相同。您对 ifelse()
的输入是长度为 1 的 max(x) > 1000
,因此结果将为长度 1。您可以使用 lapply
代替 for
,使用 if(){}else{}
代替ifelse()
:
df[] <- lapply(df, function(x) if(max(x, na.rm = TRUE) > 1000) {x / 1000}else{x})
但是使用 *apply family functions 你必须返回并在另一个步骤中更改名称---在这种情况下我通常更喜欢 for
。
但我可能会这样做而不循环:
cols_over_1000 = sapply(df, max, na.rm = TRUE) > 1000
df[cols_over_1000] = df[cols_over_1000] / 1000
names(df)[cols_over_1000] = paste(names(df)[cols_over_1000], "(in '000)")
或在dplyr
:
library(dplyr)
df %>%
mutate(across(
where(~ any(. > 1000)),
~ . / 1000,
.names = "{.col} (in '000)"
))
您可以像这样尝试 purrr
包:
library(dplyr)
library(purrr)
my_fun <- function(x,y){
if(max(x, na.rm = T)>1000){
return(rename_with(tibble(x/1000),~paste0(y,"(in '000)")))
}else{return(rename_with(tibble(x),~y))}
}
map2_dfc(df,names(df),my_fun)
我想编写一个非常简单的程序:它应该遍历数据框中的所有列,如果至少有一个观察值大于 1000,那么程序应该将该变量除以 1000,然后将 "in (000)"
添加到变量名。
我的解决方案
set.seed(42)
df <- data.frame("Norm" = rnorm(100, 1000, 0.1), rexp(100))
for (var in seq_len(ncol(df))) {
if (max(df[, var], na.rm = T) > 1000) {
df[, var] <- df[, var] / 1000
colnames(df)[var] <- print(paste(colnames(df[var]), "(in 000')"))
}
}
不过我觉得有点不方便。我认为这里不需要循环。我试着用应用来做,但我不确定为什么我得到的是除以 1000 的列的最大值,而不是每个值除以 1000 的数据框:
apply(df, 2, function(x) ifelse(max(x) > 1000, x/1000, x))
Norm rexp.100.
0.9999925 0.4473922
你知道如何不用循环来完成吗?
ab1k <- sapply(df, function(x) any(x > 1000))
df[ab1k] <- df[ab1k]/1000
names(df)[ab1k] <- paste(names(df)[ab1k], "(in 000')")
apply
用于矩阵,不要在数据帧上使用它。 ifelse
用于矢量测试 - 输出与输入的形状相同。您对 ifelse()
的输入是长度为 1 的 max(x) > 1000
,因此结果将为长度 1。您可以使用 lapply
代替 for
,使用 if(){}else{}
代替ifelse()
:
df[] <- lapply(df, function(x) if(max(x, na.rm = TRUE) > 1000) {x / 1000}else{x})
但是使用 *apply family functions 你必须返回并在另一个步骤中更改名称---在这种情况下我通常更喜欢 for
。
但我可能会这样做而不循环:
cols_over_1000 = sapply(df, max, na.rm = TRUE) > 1000
df[cols_over_1000] = df[cols_over_1000] / 1000
names(df)[cols_over_1000] = paste(names(df)[cols_over_1000], "(in '000)")
或在dplyr
:
library(dplyr)
df %>%
mutate(across(
where(~ any(. > 1000)),
~ . / 1000,
.names = "{.col} (in '000)"
))
您可以像这样尝试 purrr
包:
library(dplyr)
library(purrr)
my_fun <- function(x,y){
if(max(x, na.rm = T)>1000){
return(rename_with(tibble(x/1000),~paste0(y,"(in '000)")))
}else{return(rename_with(tibble(x),~y))}
}
map2_dfc(df,names(df),my_fun)