如何制作数据框百分比的某些部分?
How to make certain portions of a data frame percentages?
这是我的数据框 cat_data
打印(cat_data)
Metrics 2016 2017 2018
Number of Cats 100 120 150
Number Leaving 32 40 65
Number Staying 68 80 85
Percent of Leavers .32 .33 .43
Percent of Stayers .68 .67 .57
我只想将行和 5 转换为带有百分比符号的百分比。
这是我想要的输出。
Metrics 2016 2017 2018
Number of Cats 100 120 150
Number Leaving 32 40 65
Number Staying 68 80 85
Percent of Leavers 32% 33% 43%
Percent of Stayers 68% 67% 57%
我试过了,但无法正常工作。
cat_data[4:5,2:4] <- paste0(cat_data[4:5,2:4] * 100,%)
谁能告诉我需要修复什么?谢谢你。
您的代码无法运行,因为 paste0()
向量化,并且您的 table 未正确设置以允许向量化。
有点笨拙,但你可以这样做:
cat_data <- tibble::tribble(
~"Metrics", ~"2016", ~"2017", ~"2018",
"Number of Cats", 100, 120, 150,
"Number Leaving", 32, 40, 65,
"Number Staying", 68, 80, 85,
"Percent of Leavers", .32 , .33, .43,
"Percent of Stayers", .68, .67, .57) # create data
percent_data <- cat_data[4:5,] # separate percent rows
cat_data <- cat_data[-(4:5),] # remove percent rows
for (i in 2:4) { # apply the desired transformation to each column
percent_data[[i]] <- paste0(percent_data[[i]] * 100, "%")
}
cat_data <- rbind(cat_data, percent_data) # bind them back
cat_data
# A tibble: 5 x 4
Metrics `2016` `2017` `2018`
<chr> <chr> <chr> <chr>
1 Number of Cats 100 120 150
2 Number Leaving 32 40 65
3 Number Staying 68 80 85
4 Percent of Leavers 32% 33% 43%
5 Percent of Stayers 68% 67% 57%
您确定要使用 R 中的数据框执行此操作吗?最好在任何分析结束时对数字进行格式化以显示它们,在数据框中进行格式化是一种不寻常的选择。
从问题中不清楚您的列的格式是什么。它们是数字、因子还是字符?
不知道这一点,在 base R 中执行此操作的最佳方法可能是在每一列中使用 lapply
,通过字符将其转换为数字,将任何小于 1 的值乘以 100,转换将整列转换为字符格式,然后在转换后的数字后附加一个百分号。
但是,这会让您将整个数据框转换为字符串,因此您将无法在不进一步转换的情况下对它们进行数学运算。最好重新考虑您将如何使用或呈现数据。
也就是说,这是上述方法的实现:
as.data.frame(lapply(df, function(x)
{
if(!any(grepl("Number", x)))
{
x <- as.numeric(as.character(x))
s <- which(x < 1)
x[s] <- x[s] * 100
x <- as.character(x)
x[s] <- paste0(x[s], "%")
}
return(x)
}))
#> Metrics X2016 X2017 X2018
#>1 Number of Cats 100 120 150
#>2 Number Leaving 32 40 65
#>3 Number Staying 68 80 85
#>4 Percent of Leavers 32% 33% 43%
#>5 Percent of Stayers 68% 67% 57%
这应该也有效
编辑
粘贴函数需要一个向量作为输入,但您的输入 cat_data[4:5,2:4]
是一个数据框。
apply
函数以数组为输入,输出一个向量。
cat_data[4:5,2:4] <- apply(cat_data[4:5,2:4]*100, 2, function(x) paste0(x, "%"))
您将数据框的区域乘以 100。这将是您在 apply
函数中的数组输入。
通过指示 margin = 2
,矢量化按列执行。然后你提供应用于向量的函数,在本例中是 paste
函数和你想要的 %
字符。
正如@Phil 在他的回答中提到的,问题是您的数据类型存在冲突。您必须将字段 2016、2017 和 2018 的值转换为字符。一种方法是像这样改变这些字段:
# load packages
library(tidyverse)
library(scales) # package with function for converting decimal to percent
df %>%
rowwise() %>%
mutate(`2016` = if_else(str_detect(Metrics, "Percent"), scales::percent(`2016`, accuracy = 1), as.character(`2016`))) %>%
mutate(`2017` = if_else(str_detect(Metrics, "Percent"), scales::percent(`2017`, accuracy = 1), as.character(`2017`))) %>%
mutate(`2018` = if_else(str_detect(Metrics, "Percent"), scales::percent(`2018`, accuracy = 1), as.character(`2018`)))
# # A tibble: 5 x 4
# Metrics `2016` `2017` `2018`
# <fct> <chr> <chr> <chr>
# 1 Number of Cats 100 120 150
# 2 Number Leaving 32 40 65
# 3 Number Staying 68 80 85
# 4 Percent of Leavers 32% 33% 43%
# 5 Percent of Stayers 68% 67% 57%
这是一个 tidyverse 解决方案。很难知道您的数据结构是什么,但它不是 'tidy'。我假设您正在尝试创建摘要 table。我之前尝试做同样的事情时遇到过类似的问题。将 mutate_at 函数与 case_when 一起使用是一种方法,如果要包含 % 符号,则列必须是字符。
library(dplyr)
library(stringr)
a <- c("Metrics", "Number of Cats", "Number Leaving", "Number Staying", "Percent of Leavers", "Percent of Stayers")
b <- c(2016, 100, 32, 68, .32, .68)
c <- c(2017, 120, 40, 80, .33, .67)
d <- c(2018, 150, 65, 85, .43, .57)
df <- tibble(a = a ,b = b, c = c, d = d)
df %>%
mutate_at(.vars = c("b", "c", "d"), .funs = list(~case_when(a %in% c("Percent of Leavers", "Percent of Stayers") ~ str_c(round(.x*100), " %"),
TRUE ~ as.character(.x))))
#OUTPUT
a b c d
<chr> <chr> <chr> <chr>
1 Metrics 2016 2017 2018
2 Number of Cats 100 120 150
3 Number Leaving 32 40 65
4 Number Staying 68 80 85
5 Percent of Leavers 32 % 33 % 43 %
6 Percent of Stayers 68 % 67 % 57 %
这是我的数据框 cat_data
打印(cat_data)
Metrics 2016 2017 2018
Number of Cats 100 120 150
Number Leaving 32 40 65
Number Staying 68 80 85
Percent of Leavers .32 .33 .43
Percent of Stayers .68 .67 .57
我只想将行和 5 转换为带有百分比符号的百分比。
这是我想要的输出。
Metrics 2016 2017 2018
Number of Cats 100 120 150
Number Leaving 32 40 65
Number Staying 68 80 85
Percent of Leavers 32% 33% 43%
Percent of Stayers 68% 67% 57%
我试过了,但无法正常工作。
cat_data[4:5,2:4] <- paste0(cat_data[4:5,2:4] * 100,%)
谁能告诉我需要修复什么?谢谢你。
您的代码无法运行,因为 paste0()
向量化,并且您的 table 未正确设置以允许向量化。
有点笨拙,但你可以这样做:
cat_data <- tibble::tribble(
~"Metrics", ~"2016", ~"2017", ~"2018",
"Number of Cats", 100, 120, 150,
"Number Leaving", 32, 40, 65,
"Number Staying", 68, 80, 85,
"Percent of Leavers", .32 , .33, .43,
"Percent of Stayers", .68, .67, .57) # create data
percent_data <- cat_data[4:5,] # separate percent rows
cat_data <- cat_data[-(4:5),] # remove percent rows
for (i in 2:4) { # apply the desired transformation to each column
percent_data[[i]] <- paste0(percent_data[[i]] * 100, "%")
}
cat_data <- rbind(cat_data, percent_data) # bind them back
cat_data
# A tibble: 5 x 4
Metrics `2016` `2017` `2018`
<chr> <chr> <chr> <chr>
1 Number of Cats 100 120 150
2 Number Leaving 32 40 65
3 Number Staying 68 80 85
4 Percent of Leavers 32% 33% 43%
5 Percent of Stayers 68% 67% 57%
您确定要使用 R 中的数据框执行此操作吗?最好在任何分析结束时对数字进行格式化以显示它们,在数据框中进行格式化是一种不寻常的选择。
从问题中不清楚您的列的格式是什么。它们是数字、因子还是字符?
不知道这一点,在 base R 中执行此操作的最佳方法可能是在每一列中使用 lapply
,通过字符将其转换为数字,将任何小于 1 的值乘以 100,转换将整列转换为字符格式,然后在转换后的数字后附加一个百分号。
但是,这会让您将整个数据框转换为字符串,因此您将无法在不进一步转换的情况下对它们进行数学运算。最好重新考虑您将如何使用或呈现数据。
也就是说,这是上述方法的实现:
as.data.frame(lapply(df, function(x)
{
if(!any(grepl("Number", x)))
{
x <- as.numeric(as.character(x))
s <- which(x < 1)
x[s] <- x[s] * 100
x <- as.character(x)
x[s] <- paste0(x[s], "%")
}
return(x)
}))
#> Metrics X2016 X2017 X2018
#>1 Number of Cats 100 120 150
#>2 Number Leaving 32 40 65
#>3 Number Staying 68 80 85
#>4 Percent of Leavers 32% 33% 43%
#>5 Percent of Stayers 68% 67% 57%
这应该也有效
编辑
粘贴函数需要一个向量作为输入,但您的输入 cat_data[4:5,2:4]
是一个数据框。
apply
函数以数组为输入,输出一个向量。
cat_data[4:5,2:4] <- apply(cat_data[4:5,2:4]*100, 2, function(x) paste0(x, "%"))
您将数据框的区域乘以 100。这将是您在 apply
函数中的数组输入。
通过指示 margin = 2
,矢量化按列执行。然后你提供应用于向量的函数,在本例中是 paste
函数和你想要的 %
字符。
正如@Phil 在他的回答中提到的,问题是您的数据类型存在冲突。您必须将字段 2016、2017 和 2018 的值转换为字符。一种方法是像这样改变这些字段:
# load packages
library(tidyverse)
library(scales) # package with function for converting decimal to percent
df %>%
rowwise() %>%
mutate(`2016` = if_else(str_detect(Metrics, "Percent"), scales::percent(`2016`, accuracy = 1), as.character(`2016`))) %>%
mutate(`2017` = if_else(str_detect(Metrics, "Percent"), scales::percent(`2017`, accuracy = 1), as.character(`2017`))) %>%
mutate(`2018` = if_else(str_detect(Metrics, "Percent"), scales::percent(`2018`, accuracy = 1), as.character(`2018`)))
# # A tibble: 5 x 4
# Metrics `2016` `2017` `2018`
# <fct> <chr> <chr> <chr>
# 1 Number of Cats 100 120 150
# 2 Number Leaving 32 40 65
# 3 Number Staying 68 80 85
# 4 Percent of Leavers 32% 33% 43%
# 5 Percent of Stayers 68% 67% 57%
这是一个 tidyverse 解决方案。很难知道您的数据结构是什么,但它不是 'tidy'。我假设您正在尝试创建摘要 table。我之前尝试做同样的事情时遇到过类似的问题。将 mutate_at 函数与 case_when 一起使用是一种方法,如果要包含 % 符号,则列必须是字符。
library(dplyr)
library(stringr)
a <- c("Metrics", "Number of Cats", "Number Leaving", "Number Staying", "Percent of Leavers", "Percent of Stayers")
b <- c(2016, 100, 32, 68, .32, .68)
c <- c(2017, 120, 40, 80, .33, .67)
d <- c(2018, 150, 65, 85, .43, .57)
df <- tibble(a = a ,b = b, c = c, d = d)
df %>%
mutate_at(.vars = c("b", "c", "d"), .funs = list(~case_when(a %in% c("Percent of Leavers", "Percent of Stayers") ~ str_c(round(.x*100), " %"),
TRUE ~ as.character(.x))))
#OUTPUT
a b c d
<chr> <chr> <chr> <chr>
1 Metrics 2016 2017 2018
2 Number of Cats 100 120 150
3 Number Leaving 32 40 65
4 Number Staying 68 80 85
5 Percent of Leavers 32 % 33 % 43 %
6 Percent of Stayers 68 % 67 % 57 %