计算每列中的频率乘积

时间:2018-04-30 05:27:33

标签: r count dplyr summarize

我有一个包含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列频率的乘积

2 个答案:

答案 0 :(得分:2)

使用lapplyMap&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