相对 frequencies/proportions 与 dplyr 创建新列而不是行
Relative frequencies/proportions with dplyr create new columns instead of rows
这个问题的灵感来自this and 问题。
我正在尝试计算每个组中不同值的比例,但我不想为组创建 "new" 行,而是创建新列。
以上面第二个问题为例。如果我有以下数据:
data <- structure(list(value = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L,
2L, 2L, 2L, 3L, 3L, 3L, 3L), class = structure(c(1L, 1L, 1L,
2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L), .Label = c("A",
"B"), class = "factor")), .Names = c("value", "class"), class = "data.frame", row.names = c(NA,
-16L))
我可以计算每个值(1,2,3)在每个class(A,B)中的比例:
data %>%
group_by(value, class) %>%
summarise(n = n()) %>%
complete(class, fill = list(n = 0)) %>%
group_by(class) %>%
mutate(freq = n / sum(n))
# A tibble: 6 x 4
value class n freq
<int> <fctr> <dbl> <dbl>
1 1 A 3 0.2727273
2 1 B 3 0.6000000
3 2 A 4 0.3636364
4 2 B 2 0.4000000
5 3 A 4 0.3636364
6 3 B 0 0.0000000
但是我最终为每个 value/class 对添加了一行,而不是我想要这样的东西:
# some code
# A tibble: 6 x 4
class n 1 2 3
<fctr> <dbl> <dbl> <dbl> <dbl>
1 A 11 0.2727273 0.3636364 0.3636364
2 B 5 0.6000000 0.4000000 0.0000000
每组一列。我可以编写 for 循环以从旧数据框构建新数据框,但我确信有更好的方法。有什么建议吗?
谢谢
最后我们可以用pivot_wider
library(dplyr)
library(tidyr)
data %>%
group_by(value, class) %>%
summarise(n = n()) %>%
complete(class, fill = list(n = 0)) %>%
group_by(class) %>%
mutate(freq = n / sum(n), n = sum(n)) %>%
pivot_wider(names_from = value, values_from = freq)
# A tibble: 2 x 5
# Groups: class [2]
# class n `1` `2` `3`
# <fct> <dbl> <dbl> <dbl> <dbl>
#1 A 11 0.273 0.364 0.364
#2 B 5 0.6 0.4 0
或者如@IcecreamToucan 所述,不需要 complete
,因为 pivot_wider
可以选择填充自定义值(默认为 NA)
data %>%
group_by(value, class) %>%
summarise(n = n()) %>%
group_by(class) %>%
mutate(freq = n / sum(n), n = sum(n)) %>%
pivot_wider(names_from = value, values_from = freq, values_fill = list(freq = 0))
如果我们使用的是 tidyr
的早期版本,则使用 spread
data %>%
group_by(value, class) %>%
summarise(n = n()) %>%
complete(class, fill = list(n = 0)) %>%
group_by(class) %>%
mutate(freq = n / sum(n), n = sum(n)) %>%
spread(value, freq)
方法使用 data.table::dcast
而不是 pivot_wider
。
第 1 行:为每个(值,class)组获取计数(.N
),并将其命名为 n
第 2 行:在每个 class
组中创建新变量:
N
,前面计数的总和
pct
,N
的百分比每个n
组成
第 3 行:以 class
和 N
作为行,value
作为列名,pct
作为列元素转换为宽,空元素设置为 0.
library(magrittr) # For %>%. Not necessary if dplyr is loaded already
library(data.table)
setDT(data)
data[, .(n = .N), by = .(value, class)] %>%
.[, `:=`(N = sum(n), pct = n/sum(n)), by = class] %>%
dcast(class + N ~ value, value.var = 'pct', fill = 0)
# class N 1 2 3
# 1: A 11 0.2727273 0.3636364 0.3636364
# 2: B 5 0.6000000 0.4000000 0.0000000
我们可以用count
统计value
和class
、group_by
class
的出现次数,计算出频率,得到宽格式的数据.
library(dplyr)
library(tidyr)
data %>%
count(value, class) %>%
group_by(class) %>%
mutate(freq = n/sum(n), n = sum(n)) %>%
pivot_wider(names_from = value, values_from = freq, values_fill = list(freq = 0))
# class n `1` `2` `3`
# <fct> <int> <dbl> <dbl> <dbl>
#1 A 11 0.273 0.364 0.364
#2 B 5 0.6 0.4 0
这个问题的灵感来自this and
我正在尝试计算每个组中不同值的比例,但我不想为组创建 "new" 行,而是创建新列。
以上面第二个问题为例。如果我有以下数据:
data <- structure(list(value = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L,
2L, 2L, 2L, 3L, 3L, 3L, 3L), class = structure(c(1L, 1L, 1L,
2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 1L, 1L, 1L, 1L), .Label = c("A",
"B"), class = "factor")), .Names = c("value", "class"), class = "data.frame", row.names = c(NA,
-16L))
我可以计算每个值(1,2,3)在每个class(A,B)中的比例:
data %>%
group_by(value, class) %>%
summarise(n = n()) %>%
complete(class, fill = list(n = 0)) %>%
group_by(class) %>%
mutate(freq = n / sum(n))
# A tibble: 6 x 4
value class n freq
<int> <fctr> <dbl> <dbl>
1 1 A 3 0.2727273
2 1 B 3 0.6000000
3 2 A 4 0.3636364
4 2 B 2 0.4000000
5 3 A 4 0.3636364
6 3 B 0 0.0000000
但是我最终为每个 value/class 对添加了一行,而不是我想要这样的东西:
# some code
# A tibble: 6 x 4
class n 1 2 3
<fctr> <dbl> <dbl> <dbl> <dbl>
1 A 11 0.2727273 0.3636364 0.3636364
2 B 5 0.6000000 0.4000000 0.0000000
每组一列。我可以编写 for 循环以从旧数据框构建新数据框,但我确信有更好的方法。有什么建议吗?
谢谢
最后我们可以用pivot_wider
library(dplyr)
library(tidyr)
data %>%
group_by(value, class) %>%
summarise(n = n()) %>%
complete(class, fill = list(n = 0)) %>%
group_by(class) %>%
mutate(freq = n / sum(n), n = sum(n)) %>%
pivot_wider(names_from = value, values_from = freq)
# A tibble: 2 x 5
# Groups: class [2]
# class n `1` `2` `3`
# <fct> <dbl> <dbl> <dbl> <dbl>
#1 A 11 0.273 0.364 0.364
#2 B 5 0.6 0.4 0
或者如@IcecreamToucan 所述,不需要 complete
,因为 pivot_wider
可以选择填充自定义值(默认为 NA)
data %>%
group_by(value, class) %>%
summarise(n = n()) %>%
group_by(class) %>%
mutate(freq = n / sum(n), n = sum(n)) %>%
pivot_wider(names_from = value, values_from = freq, values_fill = list(freq = 0))
如果我们使用的是 tidyr
的早期版本,则使用 spread
data %>%
group_by(value, class) %>%
summarise(n = n()) %>%
complete(class, fill = list(n = 0)) %>%
group_by(class) %>%
mutate(freq = n / sum(n), n = sum(n)) %>%
spread(value, freq)
方法使用 data.table::dcast
而不是 pivot_wider
。
第 1 行:为每个(值,class)组获取计数(.N
),并将其命名为 n
第 2 行:在每个 class
组中创建新变量:
N
,前面计数的总和pct
,N
的百分比每个n
组成
第 3 行:以 class
和 N
作为行,value
作为列名,pct
作为列元素转换为宽,空元素设置为 0.
library(magrittr) # For %>%. Not necessary if dplyr is loaded already
library(data.table)
setDT(data)
data[, .(n = .N), by = .(value, class)] %>%
.[, `:=`(N = sum(n), pct = n/sum(n)), by = class] %>%
dcast(class + N ~ value, value.var = 'pct', fill = 0)
# class N 1 2 3
# 1: A 11 0.2727273 0.3636364 0.3636364
# 2: B 5 0.6000000 0.4000000 0.0000000
我们可以用count
统计value
和class
、group_by
class
的出现次数,计算出频率,得到宽格式的数据.
library(dplyr)
library(tidyr)
data %>%
count(value, class) %>%
group_by(class) %>%
mutate(freq = n/sum(n), n = sum(n)) %>%
pivot_wider(names_from = value, values_from = freq, values_fill = list(freq = 0))
# class n `1` `2` `3`
# <fct> <int> <dbl> <dbl> <dbl>
#1 A 11 0.273 0.364 0.364
#2 B 5 0.6 0.4 0