计算相似行的频率但保持数据帧的大小相同

Calculate the frequency of similar rows but keeping the same size of dataframe

我有一个包含重复行的数据框,我有一个函数可以计算相似行的频率。 这是我的样本

#############
###Sample####
#############

ID=seq(from=1,to=12,by=1)
var1=c(rep("a",12))
var2=c(rep("b",12))
var3=c("c","c","b","d","e","f","g","h","i","j","k","k")
df=data.frame(ID,var1,var2,var3)

   ID var1 var2 var3
1   1    a    b    c
2   2    a    b    c
3   3    a    b    b
4   4    a    b    d
5   5    a    b    e
6   6    a    b    f
7   7    a    b    g
8   8    a    b    h
9   9    a    b    i
10 10    a    b    j
11 11    a    b    k
12 12    a    b    k

###############
# function ####
###############

freq.f<- function(data){
  vari=colnames(data[2:ncol(data)])
  data  %>%     
    dplyr:: count(!!! rlang::syms(vari))  %>%
    mutate(frequency = n/sum(n))
  
}

# current output
freq.f(df)
   var1 var2 var3 n  frequency
1     a    b    b 1 0.08333333
2     a    b    c 2 0.16666667
3     a    b    d 1 0.08333333
4     a    b    e 1 0.08333333
5     a    b    f 1 0.08333333
6     a    b    g 1 0.08333333
7     a    b    h 1 0.08333333
8     a    b    i 1 0.08333333
9     a    b    j 1 0.08333333
10    a    b    k 2 0.16666667

我想要的是计算这个频率但保留我的所有记录,因为我的 ID 是不同的人,即使他们有相同的行信息,我也希望能够在我的输出中打印 ID 以跟踪个人。所以期望的输出是

# desired output

   ID var1 var2 var3 n  freq
1   1    a    b    c 2  0.16666667
2   2    a    b    c 2  0.16666667
3   3    a    b    b 1  0.08333333
4   4    a    b    d 1  0.08333333
5   5    a    b    e 1  0.08333333
6   6    a    b    f 1  0.08333333
7   7    a    b    g 1  0.08333333
8   8    a    b    h 1  0.08333333
9   9    a    b    i 1  0.08333333
10 10    a    b    j 1  0.08333333
11 11    a    b    k 2  0.16666667
12 12    a    b    k 2  0.16666667

我真的查看了几乎所有 post 中关于频率的内容,但找不到我的答案。预先感谢您的帮助。

在您的函数中添加联接可提供预期的结果。

freq.f<- function(data){
  vari=colnames(data[2:ncol(data)])
  inner_join(data, data  %>%     ##this is the new line
    dplyr:: count(!!! rlang::syms(vari))  %>%
    mutate(frequency = n/sum(n)))
}
freq.f(df)

   ID var1 var2 var3 n  frequency
1   1    a    b    c 2 0.16666667
2   2    a    b    c 2 0.16666667
3   3    a    b    b 1 0.08333333
4   4    a    b    d 1 0.08333333
5   5    a    b    e 1 0.08333333
6   6    a    b    f 1 0.08333333
7   7    a    b    g 1 0.08333333
8   8    a    b    h 1 0.08333333
9   9    a    b    i 1 0.08333333
10 10    a    b    j 1 0.08333333
11 11    a    b    k 2 0.16666667
12 12    a    b    k 2 0.16666667

如果您愿意使用 data.table 而不是 dplyr,则有一个非常自然的语法:

# convert df to data.table
dt = data.table(df)

# for each unique (var1, var2, var3), calculate the frequency 
# by=.(var1, var2, var3) does the grouping
# .N is the number of rows in the group
# freq := .... makes a new column called 'freq' and stores the associated value.
> dt[, freq := .N/nrow(dt), by=.(var1, var2, var3)]
> dt
       ID   var1   var2   var3       freq
    <num> <char> <char> <char>      <num>
 1:     1      a      b      c 0.16666667
 2:     2      a      b      c 0.16666667
 3:     3      a      b      b 0.08333333
 4:     4      a      b      d 0.08333333
 5:     5      a      b      e 0.08333333
 6:     6      a      b      f 0.08333333
 7:     7      a      b      g 0.08333333
 8:     8      a      b      h 0.08333333
 9:     9      a      b      i 0.08333333
10:    10      a      b      j 0.08333333
11:    11      a      b      k 0.16666667
12:    12      a      b      k 0.16666667

如果您想以编程方式获取这些列,可以将 by=.(var1, var2, var3) 替换为 by=vari

@mathematical.coffee的思路也可以写成dplyr

library(dplyr)

freq.f<- function(data){

  data  %>%     
    group_by(across(-1)) %>%
    #If you are on dplyr < 1.0.0 use group_by_at
    #group_by_at(-1) %>%
    mutate(frequency = n()/nrow(.))
}

freq.f(df)

# A tibble: 12 x 5
# Groups:   var1, var2, var3 [10]
#      ID var1  var2  var3  frequency
#   <dbl> <chr> <chr> <chr>  <dbl>
# 1     1 a     b     c     0.167 
# 2     2 a     b     c     0.167 
# 3     3 a     b     b     0.0833
# 4     4 a     b     d     0.0833
# 5     5 a     b     e     0.0833
# 6     6 a     b     f     0.0833
# 7     7 a     b     g     0.0833
# 8     8 a     b     h     0.0833
# 9     9 a     b     i     0.0833
#10    10 a     b     j     0.0833
#11    11 a     b     k     0.167 
#12    12 a     b     k     0.167