如何将 sprintf 函数应用于 r 数据框以将值转换为百分比,同时保持原始数据框结构?
How to apply sprintf function to r data frame to convert values to percentages while maintaining original data frame structure?
我正在研究用于格式化数据框中所有数值的选项,而不仅仅是选定的列。当 运行 下面的代码时,我从以下称为“c”的基本数据框开始:
> c
A B
1 3.412324 2.234200
2 3.245236 4.234234
Related code:
a <- c(3.412324463,3.2452364)
b <- c(2.2342,4.234234)
c <- data.frame(A=a, B=b, stringsAsFactors = FALSE)
接下来,我将上述“c”数据框中的所有数字四舍五入到小数点后 2 位,得到如下所示的数据框“d”,并在下方显示相关代码:
> d
A B
[1,] 3.41 2.23
[2,] 3.25 4.23
Related code:
d <- as.data.frame(lapply(c, formatC, decimal.mark =".", format = "f", digits = 2))
d <- sapply(d[,],as.numeric)
最后一步,我想在一个名为“e”的新数据框中以百分比表示上述数据框“d”。我使用下面显示的代码得到以下结果列表。
> e
X.341.0.. X.325.0.. X.223.0.. X.423.0..
1 341.0% 325.0% 223.0% 423.0%
Related code:
e <- as.data.frame(lapply(d*100, sprintf, fmt = "%.1f%%"))
如何以有效的方式修改代码,以便在导出数据帧“e”时保持数据帧结构完整,就像生成数据帧“d”时那样?在 base R 和 dplyr
.
中看到解决方案将是最有帮助的
我很确定问题出在我使用 lapply()
创建数据框“e”(是的,现在我知道 lapply()
吐出列表),但它工作正常在创建数据框“d”时维护数据框结构!
数据框中的所有值都采用相同的格式,因此无需对列等进行子集化。
lapply
的问题在于它 returns 一个 list
。 data.frame
是列表的特例,但要使 lapply
修改特定结构的数据框同时保持该结构,最简单的方法是 df[] = lapply(df, ...)
。额外的 []
保留现有结构。
## d better base version
## `round` is friendlier than `sprintf` - it returns numerics
d = c
d[] = lapply(d, round, 2)
d
# A B
# 1 3.41 2.23
# 2 3.25 4.23
## dplyr version
d_dplyr = c %>%
mutate(across(everything(), round, 2))
d_dplyr
# A B
# 1 3.41 2.23
# 2 3.25 4.23
## e base
e = d
e[] = lapply(e * 100, sprintf, fmt = "%.1f%%")
e
# A B
# 1 341.0% 223.0%
# 2 325.0% 423.0%
## e dplyr
## in `tidyverse`, we'll use `scales::percent_format`
## which generates a percent conversion function according to specification
## the default already multiplies by 100 and adds the `%` sign
## we just need to specify the accuracy.
## (note that we can easily start from `c` again)
e_dplyr = c %>%
mutate(across(everything(), scales::percent_format(accuracy = 0.1)))
e_dplyr
# A B
# 1 341.2% 223.4%
# 2 324.5% 423.4%
我正在研究用于格式化数据框中所有数值的选项,而不仅仅是选定的列。当 运行 下面的代码时,我从以下称为“c”的基本数据框开始:
> c
A B
1 3.412324 2.234200
2 3.245236 4.234234
Related code:
a <- c(3.412324463,3.2452364)
b <- c(2.2342,4.234234)
c <- data.frame(A=a, B=b, stringsAsFactors = FALSE)
接下来,我将上述“c”数据框中的所有数字四舍五入到小数点后 2 位,得到如下所示的数据框“d”,并在下方显示相关代码:
> d
A B
[1,] 3.41 2.23
[2,] 3.25 4.23
Related code:
d <- as.data.frame(lapply(c, formatC, decimal.mark =".", format = "f", digits = 2))
d <- sapply(d[,],as.numeric)
最后一步,我想在一个名为“e”的新数据框中以百分比表示上述数据框“d”。我使用下面显示的代码得到以下结果列表。
> e
X.341.0.. X.325.0.. X.223.0.. X.423.0..
1 341.0% 325.0% 223.0% 423.0%
Related code:
e <- as.data.frame(lapply(d*100, sprintf, fmt = "%.1f%%"))
如何以有效的方式修改代码,以便在导出数据帧“e”时保持数据帧结构完整,就像生成数据帧“d”时那样?在 base R 和 dplyr
.
我很确定问题出在我使用 lapply()
创建数据框“e”(是的,现在我知道 lapply()
吐出列表),但它工作正常在创建数据框“d”时维护数据框结构!
数据框中的所有值都采用相同的格式,因此无需对列等进行子集化。
lapply
的问题在于它 returns 一个 list
。 data.frame
是列表的特例,但要使 lapply
修改特定结构的数据框同时保持该结构,最简单的方法是 df[] = lapply(df, ...)
。额外的 []
保留现有结构。
## d better base version
## `round` is friendlier than `sprintf` - it returns numerics
d = c
d[] = lapply(d, round, 2)
d
# A B
# 1 3.41 2.23
# 2 3.25 4.23
## dplyr version
d_dplyr = c %>%
mutate(across(everything(), round, 2))
d_dplyr
# A B
# 1 3.41 2.23
# 2 3.25 4.23
## e base
e = d
e[] = lapply(e * 100, sprintf, fmt = "%.1f%%")
e
# A B
# 1 341.0% 223.0%
# 2 325.0% 423.0%
## e dplyr
## in `tidyverse`, we'll use `scales::percent_format`
## which generates a percent conversion function according to specification
## the default already multiplies by 100 and adds the `%` sign
## we just need to specify the accuracy.
## (note that we can easily start from `c` again)
e_dplyr = c %>%
mutate(across(everything(), scales::percent_format(accuracy = 0.1)))
e_dplyr
# A B
# 1 341.2% 223.4%
# 2 324.5% 423.4%