0

我有一个包含 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 

我想创建第四列,它将包含每一行每个值与每个组的频率的乘积。因此,例如,“Freq”列的第一个值将是 A 列中 0 的频率、B 列中 1 的频率和 C 列中 0.1 的频率的乘积。

如何使用 dplyr/baseR 有效地做到这一点?

需要强调的是,这不是每个总行的组合频率,而是 1 列频率的乘积

4

2 回答 2

2

使用基础 R中lapply, Map&的组合的一种有效方法: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相乘,然后是第二个值,等等。

相同的方法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))
于 2018-04-30T06:10:37.930 回答
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
于 2018-04-30T06:10:35.487 回答