在R中按组设置模式

4

我需要计算每个年龄组身份证号码的众数。假设以下表格:

library(data.table)
DT = data.table(age=c(12,12,3,3,12),v=rnorm(5), number=c("122","125","5","5","122"))

所以我创建了一个函数:
g <- function(number) {
      ux <- unique(number)
      ux[which.max(tabulate(match(number, ux)))]
    }
H<-function(tabla){data.frame(MODA=g, count=nrow(tabla))}
clasif_edad1<-ddply(DF,.(age), H)
View(clasif_edad1)

但是我遇到了以下错误:
Error: arguments imply differing number of rows: 0, 1

输出结果应为:
age      v    number moda
12  0,631152199 122 122
12  0,736648714 125 122
3   0,545921527 5   5
3   0,59336284  5   5
12  0,836685437 122 122

不知道问题出在哪里。

谢谢。


你的函数有点不清楚。能否展示一下你想要的输出结果?再次提醒,没有任何理由将 data.table 转换为 data.frame,然后再使用 plyrdata.table 是 R 之王,直接使用即可。 - David Arenburg
1
如果您希望我们重现您的列“v”,则需要使用“set.seed”,因为“rnorm”每次运行时都会生成一个随机种子。 - David Arenburg
5个回答

2

一种方法:

> myfun <- function(x) unique(x)[which.max(table(x))]
> DT[ , moda := myfun(number), by = age]
> DT
   age          v number moda
1:  12 -0.9740026    122  122
2:  12  0.6893727    125  122
3:   3 -0.9558391      5    5
4:   3 -1.2317071      5    5
5:  12 -0.9568919    122  122

这似乎是使用 data.table 完成此操作的惯用方式。 - David Arenburg
我正在处理大约4百万行的数据,这需要很长时间才能运行--通过分组查找大约4个值的模式会将创建一个包含其他10个变量的新数据表所需的时间增加6倍。有没有更有效地查找模式的方法?目前我的计划是要么降采样,要么让程序在夜间运行。 - verybadatthis
@verybadatthis 我想在R中没有更快的方法了。 - Sven Hohenstein
实际上,在写完这篇文章后,我在这里找到了一个略微更快的方法。它与你在这里做的非常相似,只是稍微向量化并分开了一些步骤。 - verybadatthis

0
modef <- function(V)
{ 
k = 1
prev='xxxx'
max_value = 0
for (i in V)
{
if (prev == i)
{ 
k = k+1
}
else
{
if (k > max_value) 
{
MODE_CALC = data.frame( 
number = c(prev) , 
occurence = c(k) )
max_value = k
k = 1
}
k = 1
}
prev = i
}
print(MODE_CALC$number)
}
V = c(11, 11, 11, 11, 12, 12, 2, 2, 2, 2, 2, 2, 14, 14, 14, 15, 16, 17, 17, 17 ,17 , 
17, 18, 19)    
modef(sort(V))

0
library(janitor)
mode_ <- function(x) tabyl(x) |> filter(n == max(n)) |> pull(x) |> head(1)

1
如果您能解释一下这个程序的作用,特别是使用Janitor表格相比基本表格的优势,那将会很有帮助。 - camille

0
你可以使用 dplyr 来实现这个功能:
library(dplyr)
modes_by_age <- summarise(group_by(DT, age), group_mode = g(number))
inner_join(DT, modes_by_age)

这将输出您想要的结果。
Source: local data table [5 x 4]

  age         v number group_mode
1   3 0.5524352      5          5
2   3 0.2869912      5          5
3  12 0.8987475    122        122
4  12 0.9740715    125        122
5  12 2.5058450    122        122

0
这是一个基于R语言的解决方案。你可以为每个组计算众数,然后将其与原始数据合并:
merge(DT, setNames(aggregate(number~age, data=DT, g), c("age", "moda")), by="age")
#    age          v number moda
# 1:   3  1.7148357      5    5
# 2:   3  0.9504811      5    5
# 3:  12 -0.7648237    122  122
# 4:  12  0.9011115    125  122
# 5:  12 -0.8718779    122  122

可能有一种特定于数据表的方法,但即使 DT 是一个数据框架,这种方法也可以使用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接