我有一个包含3列的数据框,每列包含少量值:
> df
# A tibble: 364 x 3
A B C
<dbl> <dbl> <dbl>
0. 1. 0.100
0. 1. 0.200
0. 1. 0.300
0. 1. 0.500
0. 2. 0.100
0. 2. 0.200
0. 2. 0.300
0. 2. 0.600
0. 3. 0.100
0. 3. 0.200
# ... with 354 more rows
> apply(df, 2, table)
$`A`
0 1 2 3 4 5 6 7 8 9 10
34 37 31 32 27 39 29 28 37 39 31
$B
1 2 3 4 5 6 7 8 9 10 11
38 28 38 37 32 34 29 33 30 35 30
$C
0.1 0.2 0.3 0.4 0.5 0.6
62 65 65 56 60 56
我想创建第四列,它将为每一行包含每个值的每个组的频率乘积。例如,列的第一个值&#34; Freq&#34;将是A列中频率为零的频率,B列中的频率为1,C列中的频率为0.1。
如何使用dplyr / baseR有效地完成此操作?
要强调,这不是每个总行的组合频率,而是1列频率的乘积
答案 0 :(得分:2)
使用lapply
,Map
&amp;组合的有效方法来自基地R的Reduce
:
l <- lapply(df, table)
m <- Map(function(x,y) unname(y[match(x, names(y))]), df, l)
df$D <- Reduce(`*`, m)
给出:
> head(df, 15) A B C D 1 3 5 0.4 57344 2 5 6 0.5 79560 3 0 4 0.1 77996 4 2 6 0.1 65348 5 5 11 0.6 65520 6 3 8 0.5 63360 7 6 6 0.2 64090 8 1 9 0.4 62160 9 10 2 0.2 56420 10 5 2 0.2 70980 11 4 11 0.3 52650 12 7 6 0.5 57120 13 10 1 0.2 76570 14 7 10 0.5 58800 15 8 10 0.3 84175
这是做什么的:
lapply(df, table)
为每列创建频率列表Map
创建一个列表match
,其中每个列表项的长度与df
的行数相同。每个列表项都是与df
中的值对应的频率向量。Reduce
列表m
中向量的乘积是按元素计算的:列表m
中每个向量的第一个值互相叠加,然后是第2个价值等。 tidyverse
中的相同方法:
library(dplyr)
library(purrr)
df %>%
mutate(D = map(df, table) %>%
map2(df, ., function(x,y) unname(y[match(x, names(y))])) %>%
reduce(`*`))
使用过的数据:
set.seed(2018)
df <- data.frame(A = sample(rep(0:10, c(34,37,31,32,27,39,29,28,37,39,31)), 364),
B = sample(rep(1:11, c(38,28,38,37,32,34,29,33,30,35,30)), 364),
C = sample(rep(seq(0.1,0.6,0.1), c(62,65,65,56,60,56)), 364))
答案 1 :(得分:0)
将使用以下小例子
df
A B C
1 3 5 0.4
2 5 6 0.5
3 0 4 0.1
4 2 6 0.1
5 5 11 0.6
6 3 8 0.5
7 6 6 0.2
8 1 9 0.4
9 10 2 0.2
10 5 2 0.2
sapply(g,table)
$A
0 1 2 3 5 6 10
1 1 1 2 3 1 1
$B
2 4 5 6 8 9 11
2 1 1 3 1 1 1
$C
0.1 0.2 0.4 0.5 0.6
2 3 2 2 1
library(tidyverse)
df%>%
group_by(A)%>%
mutate(An=n())%>%
group_by(B)%>%
mutate(Bn=n())%>%
group_by(C)%>%
mutate(Cn=n(),prod=An*Bn*Cn)
A B C An Bn Cn prod
<int> <int> <dbl> <int> <int> <int> <int>
1 3 5 0.400 2 1 2 4
2 5 6 0.500 3 3 2 18
3 0 4 0.100 1 1 2 2
4 2 6 0.100 1 3 2 6
5 5 11 0.600 3 1 1 3
6 3 8 0.500 2 1 2 4
7 6 6 0.200 1 3 3 9
8 1 9 0.400 1 1 2 2
9 10 2 0.200 1 2 3 6
10 5 2 0.200 3 2 3 18