为每个级别的因子级别添加频率计数列并重新整形数据帧

时间:2017-07-09 21:33:15

标签: r

我有一个像这样的数据框:

 df<- data.frame(region = c("1","1","1","1","1","2","2"),
            loc = c("104","104","104","105","105","106","107"), 
            plntsp = c("A","A", "B", "C", "C", "E", "F"), 
            lepsp = c("Z","Z", "Y", "W", "X", "T", "T"))

我想: 1)找到每个plntsplepsp子集的regionloc的频率。 2)将plantsplepsp列折叠为一列标题为sp的长数据框。新计数列将折叠为一个名为freq的计数列。

output<- data.frame(region = c("1","1","1","1","2","1","1","1","2","2","2"),
loc = c("104","104","105","106","107","104","104","105","105","106","107"), 
sp = c("A","B", "C", "E", "F", "Z", "Y","W", "X", "T", "T"), 
freq = c("2","1", "2", "1", "1", "2", "1", "1", "1", "1", "1"))

我试过了:

df<- 
group_by(region,loc) %>%
summarise(freq1= length(unique(plantsp), freq2= length(unique(lepsp))
mutate(sp= df$plantsp &df$lepsp, freq= df$freq1 &df$freq2)

3 个答案:

答案 0 :(得分:1)

aggregate将是一个选项

rbind(aggregate(list(freq = seq_along(df$plntsp)),
                by = list(region = df$region,loc = df$loc, sp = df$plntsp),
                FUN = length),
      aggregate(list(freq = seq_along(df$plntsp)),
                by = list(region = df$region, loc = df$loc, sp = df$lepsp),
                FUN = length))
#   region loc sp freq
#1       1 104  A    2
#2       1 104  B    1
#3       1 105  C    2
#4       2 106  E    1
#5       2 107  F    1
#6       2 106  T    1
#7       2 107  T    1
#8       1 105  W    1
#9       1 105  X    1
#10      1 104  Y    1
#11      1 104  Z    2

在使用melt

之前使用reshape2 aggregate
library(reshape2)
opt = melt(data = df, id.vars = c("region", "loc"))
#Warning message:
#attributes are not identical across measure variables; they will be dropped 
aggregate(list(freq=opt$value), opt[c("region","loc","value")], FUN = length)
#   region loc value freq
#1       1 104     A    2
#2       1 104     B    1
#3       1 105     C    2
#4       2 106     E    1
#5       2 107     F    1
#6       2 106     T    1
#7       2 107     T    1
#8       1 105     W    1
#9       1 105     X    1
#10      1 104     Y    1
#11      1 104     Z    2

答案 1 :(得分:1)

使用tidyverse

library(tidyverse)
df %>% 
  gather(key, sp, plntsp, lepsp) %>%
  group_by(region, loc, sp) %>%
  count(.) %>%
  rename(x=n)

   region    loc    sp     x
 1      1    104     A     2
 2      1    104     B     1
 3      1    104     Y     1
 4      1    104     Z     2
 5      1    105     C     2
 6      1    105     W     1
 7      1    105     X     1
 8      2    106     E     1
 9      2    106     T     1
10      2    107     F     1
11      2    107     T     1

答案 2 :(得分:0)

data.table解决方案遵循the advice from thelatemail首先重新构造为长格式,然后计算外观。

可以从两个软件包中获取melt()从宽到长格式重塑数据的功能:reshape2data.table。出于性能原因和简洁的语法,我更喜欢后者:

library(data.table)
id_vars = c("region", "loc")
melt(setDT(df), id.vars = id_vars, value.name = "sp")[, .(freq = .N), c(id_vars, "sp")]
    region loc sp freq
 1:      1 104  A    2
 2:      1 104  B    1
 3:      1 105  C    2
 4:      2 106  E    1
 5:      2 107  F    1
 6:      1 104  Z    2
 7:      1 104  Y    1
 8:      1 105  W    1
 9:      1 105  X    1
10:      2 106  T    1
11:      2 107  T    1

请注意,列已根据OP的请求重命名。为了与远程发布的其他答案进行比较,代码更加精简,无需重命名列:

melt(setDT(df), id.vars = id_vars)[, .N, c(id_vars, "value")]