计算列中的值以创建摘要 table 的最佳方法是什么?
What is the best way to count values within columns to create a summary table?
我有一个 tbl_df
有几个列,其中有多个值。我希望使用列中的值来创建多个列。之后,我希望对这些专栏进行总结。
我可以采用的一种方法是在 mutate
中创建多个 ifelse
,但这似乎效率不高。有没有更好的方法来解决这个问题?我在想可能有一个基于 dplyr
and/or tidyr
的解决方案。
下面是我要执行的操作的示例。它只是数据和列的样本。它不包含我要创建的所有列。摘要 table 将包含一些基于 sum
和 mean
的列。
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
df <- tibble::tribble(
~type, ~bb_type, ~description,
"B", NA, "ball",
"S", NA, "foul",
"X", "line_drive", "hit_into_play_no_out",
"S", NA, "swinging_strike",
"S", NA, "foul",
"X", "ground_ball", "hit_into_play",
"S", NA, "swinging_strike",
"X", "fly_ball", "hit_into_play_score",
"B", NA, "ball",
"S", NA, "foul"
)
df <- df %>%
mutate(ground_ball = ifelse(bb_type == "ground_ball", 1, 0),
fly_ball = if_else(bb_type == "fly_ball", 1, 0),
X = if_else(type == "X", 1, 0),
# not sure if this is the based way to go about counting columns that start with swinging to sum later
swinging_strike = grepl("^swinging", description))
df
#> # A tibble: 10 x 7
#> type bb_type description ground_ball fly_ball X swinging_strike
#> <chr> <chr> <chr> <dbl> <dbl> <dbl> <lgl>
#> 1 B <NA> ball NA NA 0 FALSE
#> 2 S <NA> foul NA NA 0 FALSE
#> 3 X line_drive hit_into_play_no… 0 0 1 FALSE
#> 4 S <NA> swinging_strike NA NA 0 TRUE
#> 5 S <NA> foul NA NA 0 FALSE
#> 6 X ground_ba… hit_into_play 1 0 1 FALSE
#> 7 S <NA> swinging_strike NA NA 0 TRUE
#> 8 X fly_ball hit_into_play_sc… 0 1 1 FALSE
#> 9 B <NA> ball NA NA 0 FALSE
#> 10 S <NA> foul NA NA 0 FALSE
summary_df <- df %>%
summarize(n = n(),
fly_ball = sum(fly_ball, na.rm = TRUE),
ground_ball = sum(ground_ball, na.rm = TRUE))
summary_df
#> # A tibble: 1 x 3
#> n fly_ball ground_ball
#> <int> <dbl> <dbl>
#> 1 10 1 1
总而言之,我希望执行以下操作:
- 为
bb_type
和 type
中的所有值创建新列以计算它们
- 创建一个新列来计算描述列中以 swinging 开头的值的数量。我想看一个示例,该示例从该列中选择另一个文本字符串并创建一个包含计数的新列作为附加示例。前任。球
- 在执行我希望在 1 和 2 中实现的目标时,我将如何选择自己的名字?我必须在事后简单地使用
dplyr::rename
吗?
使用 dplyr
和 tidyr
你可以做这样的事情。首先,您可以通过指定 .drop = FALSE
按 "bb_type" 变量分组,以便 dplyr
保留 NA
值。然后,您可以对它们进行计数并获得所有计数值的总和,最后使用 pivot_wider
获取以您要查找的方向显示的数据:
library(dplyr)
library(tidyr)
df %>% group_by(bb_type, .drop = FALSE) %>%
count() %>%
ungroup() %>% mutate(Sum = sum(n)) %>%
pivot_wider(.,names_from = bb_type,values_from = n)
# A tibble: 1 x 5
Sum fly_ball ground_ball line_drive `NA`
<int> <int> <int> <int> <int>
1 10 1 1 1 7
是您要找的吗?
我们可以使用 table
和 base R
中的 addmargins
addmargins(table(df$bb_type, useNA = 'always'), 1)
# fly_ball ground_ball line_drive <NA> Sum
# 1 1 1 7 10
这似乎是一个表格请求,其中包含该表格中条目的后续计数
tb_df <- table(df$bb_type, useNA="always")
c(Sum=sum(tb_df), tb_df)
Sum fly_ball ground_ball line_drive <NA>
10 1 1 1 7
如果你想把它作为一个数据框,你首先要把它变成一个命名列表:
data.frame( as.list( c(Sum=sum(tb_df), tb_df) ) )
Sum fly_ball ground_ball line_drive NA.
1 10 1 1 1 7
如果你想在所有列上完成此操作,那么首先创建一个处理一列的函数,然后 lapply 它到 tbl_df:
tally_col <- function(x){ tb <- table(x, useNA="always")
tal <- c(Sum=sum(tb), tb); data.frame( as.list(tal)) }
lapply(df, tally_col)
# ---output---
$type
Sum B S X NA.
1 10 2 5 3 0
$bb_type
Sum fly_ball ground_ball line_drive NA.
1 10 1 1 1 7
$description
Sum ball foul hit_into_play hit_into_play_no_out hit_into_play_score swinging_strike NA.
1 10 2 3 1 1 1 2 0
我有一个 tbl_df
有几个列,其中有多个值。我希望使用列中的值来创建多个列。之后,我希望对这些专栏进行总结。
我可以采用的一种方法是在 mutate
中创建多个 ifelse
,但这似乎效率不高。有没有更好的方法来解决这个问题?我在想可能有一个基于 dplyr
and/or tidyr
的解决方案。
下面是我要执行的操作的示例。它只是数据和列的样本。它不包含我要创建的所有列。摘要 table 将包含一些基于 sum
和 mean
的列。
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
df <- tibble::tribble(
~type, ~bb_type, ~description,
"B", NA, "ball",
"S", NA, "foul",
"X", "line_drive", "hit_into_play_no_out",
"S", NA, "swinging_strike",
"S", NA, "foul",
"X", "ground_ball", "hit_into_play",
"S", NA, "swinging_strike",
"X", "fly_ball", "hit_into_play_score",
"B", NA, "ball",
"S", NA, "foul"
)
df <- df %>%
mutate(ground_ball = ifelse(bb_type == "ground_ball", 1, 0),
fly_ball = if_else(bb_type == "fly_ball", 1, 0),
X = if_else(type == "X", 1, 0),
# not sure if this is the based way to go about counting columns that start with swinging to sum later
swinging_strike = grepl("^swinging", description))
df
#> # A tibble: 10 x 7
#> type bb_type description ground_ball fly_ball X swinging_strike
#> <chr> <chr> <chr> <dbl> <dbl> <dbl> <lgl>
#> 1 B <NA> ball NA NA 0 FALSE
#> 2 S <NA> foul NA NA 0 FALSE
#> 3 X line_drive hit_into_play_no… 0 0 1 FALSE
#> 4 S <NA> swinging_strike NA NA 0 TRUE
#> 5 S <NA> foul NA NA 0 FALSE
#> 6 X ground_ba… hit_into_play 1 0 1 FALSE
#> 7 S <NA> swinging_strike NA NA 0 TRUE
#> 8 X fly_ball hit_into_play_sc… 0 1 1 FALSE
#> 9 B <NA> ball NA NA 0 FALSE
#> 10 S <NA> foul NA NA 0 FALSE
summary_df <- df %>%
summarize(n = n(),
fly_ball = sum(fly_ball, na.rm = TRUE),
ground_ball = sum(ground_ball, na.rm = TRUE))
summary_df
#> # A tibble: 1 x 3
#> n fly_ball ground_ball
#> <int> <dbl> <dbl>
#> 1 10 1 1
总而言之,我希望执行以下操作:
- 为
bb_type
和type
中的所有值创建新列以计算它们 - 创建一个新列来计算描述列中以 swinging 开头的值的数量。我想看一个示例,该示例从该列中选择另一个文本字符串并创建一个包含计数的新列作为附加示例。前任。球
- 在执行我希望在 1 和 2 中实现的目标时,我将如何选择自己的名字?我必须在事后简单地使用
dplyr::rename
吗?
使用 dplyr
和 tidyr
你可以做这样的事情。首先,您可以通过指定 .drop = FALSE
按 "bb_type" 变量分组,以便 dplyr
保留 NA
值。然后,您可以对它们进行计数并获得所有计数值的总和,最后使用 pivot_wider
获取以您要查找的方向显示的数据:
library(dplyr)
library(tidyr)
df %>% group_by(bb_type, .drop = FALSE) %>%
count() %>%
ungroup() %>% mutate(Sum = sum(n)) %>%
pivot_wider(.,names_from = bb_type,values_from = n)
# A tibble: 1 x 5
Sum fly_ball ground_ball line_drive `NA`
<int> <int> <int> <int> <int>
1 10 1 1 1 7
是您要找的吗?
我们可以使用 table
和 base R
addmargins
addmargins(table(df$bb_type, useNA = 'always'), 1)
# fly_ball ground_ball line_drive <NA> Sum
# 1 1 1 7 10
这似乎是一个表格请求,其中包含该表格中条目的后续计数
tb_df <- table(df$bb_type, useNA="always")
c(Sum=sum(tb_df), tb_df)
Sum fly_ball ground_ball line_drive <NA>
10 1 1 1 7
如果你想把它作为一个数据框,你首先要把它变成一个命名列表:
data.frame( as.list( c(Sum=sum(tb_df), tb_df) ) )
Sum fly_ball ground_ball line_drive NA.
1 10 1 1 1 7
如果你想在所有列上完成此操作,那么首先创建一个处理一列的函数,然后 lapply 它到 tbl_df:
tally_col <- function(x){ tb <- table(x, useNA="always")
tal <- c(Sum=sum(tb), tb); data.frame( as.list(tal)) }
lapply(df, tally_col)
# ---output---
$type
Sum B S X NA.
1 10 2 5 3 0
$bb_type
Sum fly_ball ground_ball line_drive NA.
1 10 1 1 1 7
$description
Sum ball foul hit_into_play hit_into_play_no_out hit_into_play_score swinging_strike NA.
1 10 2 3 1 1 1 2 0