我有一个我要为其找到模式的分类变量。特别是,我想找到可变种族群体(即最常见的种族群体)的模式。我将按家庭进行分组,即找到家庭中最常见的族裔。问题是,如果存在一种以上的模式(一个以上的种族占主导地位),那么我想从户主那里得到一个(还有另一个变量表明该人是否是户主)。
基本上,我们会有表格HQ2:
H_Code Rela_HH Ethn
1 AS-01 10 SEN
2 AS-01 1 SEN
3 AS-02 1 FA
4 AS-02 2 MA
5 AS-02 4 MA
6 AS-02 4 FA
7 AS-03 1 NZ
8 AS-03 2 MA
其中H_Code =家庭代码,Rela_HH =与户主的关系(1表示户主),Ethn =族裔群体。
您将看到AS-02具有两种模式:FA和MA。在这种情况下,我希望R给我一个Rela_HH值为1的人。
到目前为止,我刚刚设法完成了普通模式,却找不到编码附加位的方法。
Mode <- function(x) { ux <- unique(x) ux[which.max(tabulate(match(, ux)))] } HQ2$c <- with(HQ2, ave(Ethn, H_Code, FUN=Mode))
答案 0 :(得分:0)
我确定有一个很好的data.table
方法可以做到这一点。如果我提出一个答案,我将对其进行编辑。现在,我有一种使用order
和dplyr
的简单方法。请注意,Mode
函数将采用第一个Ethn
,因此我在hq2中对其进行了重新排序以进行演示。
library(dplyr)
hq2 <- data.table(H_Code = c("AS-01", "AS-01", "AS-02", "AS-02", "AS-02", "AS-02", "AS-03", "AS-03"), Rela_HH = c(10,1,1,2,4,4,2,1), Ethn = c("SEN", "SEN", "FA", "MA", "MA", "FA", "NZ", "MA"))
hq2[order(H_Code, Rela_HH), ] %>%
group_by(H_Code) %>%
summarize(Ethn_Mode = Mode(Ethn))
# A tibble: 3 x 2
H_Code Ethn_Mode
<chr> <chr>
1 AS-01 SEN
2 AS-02 MA
3 AS-03 MA
如果桌子很大,可以将键设置为H_Code
和Rela_HH
,以便更快地进行排序。
library(data.table)
hq1 <- as.data.table(hq2)
hq1[order(H_Code, Rela_HH), ][, Mode(Ethn), by = list(H_Code)]
H_Code V1
1: AS-01 SEN
2: AS-02 MA
3: AS-03 MA
编辑
这是经过修订的dplyr
代码。
hq3 %>%
group_by(H_Code, Ethn) %>%
mutate(eth_count = sum(n())) %>%
mutate(priority = all(1 %in% Rela_HH & !1 %in% eth_count)) %>%
arrange(H_Code, desc(priority), desc(eth_count), Rela_HH) %>%
ungroup() %>%
group_by(H_Code) %>%
filter(row_number() %in% 1)
这是修订的data.table
代码,它不使用任何mode
函数。它的作用是创建一个priority
列,如果有一次以上的种族发生,则将其设置为TRUE
,并且该组中的条目在1
中设置了一个Rela_HH
。然后,您可以设置排序顺序,以计算出排序顺序和任何联系(H_Code, -priority, -count, Rela_HH
)。
三个具有不同场景的数据集,hq3
(HH种族发生> 1,但<非HH),hq4
(HH种族发生1)和hq5
(HH种族发生> 1,>非HH)。
hq3 <- data.table(H_Code = c("AS-01", "AS-02", "AS-02", "AS-02", "AS-02", "AS-02", "AS-03", "AS-03"), Rela_HH = c(10,4,3,2,1,5,2,1), Ethn = c("SEN", "FA", "FA", "FA", "MA", "MA", "NZ", "MA"))
hq4 <- data.table(H_Code = c("AS-01", "AS-02", "AS-02", "AS-02", "AS-02", "AS-02", "AS-03", "AS-03"), Rela_HH = c(10,4,3,2,1,5,2,1), Ethn = c("SEN", "MA", "FA", "FA", "ZA", "MA", "NZ", "MA"))
hq5 <- data.table(H_Code = c("AS-01", "AS-02", "AS-02", "AS-02", "AS-02", "AS-02", "AS-03", "AS-03"), Rela_HH = c(10,4,3,2,1,5,2,1), Ethn = c("SEN", "MA", "FA", "FA", "MA", "MA", "NZ", "MA"))
hq3[, `:=` (count = .N), by = list(H_Code, Ethn)][, priority := all(1 %in% Rela_HH & !1 %in% count), by = list(H_Code, Ethn)][order(H_Code, Rela_HH, -count), ] # leave off the last [] section, it's here to show this output in order
H_Code Rela_HH Ethn count priority
1: AS-01 10 SEN 1 FALSE
2: AS-02 1 MA 2 TRUE
3: AS-02 2 FA 3 FALSE
4: AS-02 3 FA 3 FALSE
5: AS-02 4 FA 3 FALSE
6: AS-02 5 MA 2 TRUE
7: AS-03 1 MA 1 FALSE
8: AS-03 2 NZ 1 FALSE
hq3[order(H_Code, -priority, -count, Rela_HH), ][hq3[, .I[1], by = list(H_Code)]$V1]
H_Code Rela_HH Ethn count priority
1: AS-01 10 SEN 1 FALSE
2: AS-02 1 MA 2 TRUE
3: AS-03 1 MA 1 FALSE
哪个更快? Data.table,大约是原来的两倍,并且在大表上设置了键,也许更多。
> microbenchmark(DTmeth(hq1), dplyrmeth(hq2), neval = 1000)
Unit: nanoseconds
expr min lq mean median uq max neval cld
DTmeth(hq1) 624865 641316 665616.17 654145.5 677087 847038 100 b
dplyrmeth(hq2) 1144980 1161583 1202274.35 1180147.5 1223617 1651814 100 c
neval 0 0 3.56 1.0 1 303 100 a
经过修订的代码测试(我很好奇data.table
是否有更好的方法,因为它现在与dplyr
差不多):
Unit: nanoseconds
expr min lq mean median uq max neval cld
DTmeth(hq5) 653542 683727.5 773249.70 706670.5 747120.5 1791880 100 b
DT2meth(hq5) 1670831 1816633.0 1947881.22 1874742.5 2040164.5 2892786 100 c
dplyrmeth(hq3) 1169733 1232672.5 1587836.22 1281876.5 1367757.5 24089844 100 c
dplyr2meth(hq3) 1414848 1506917.5 1903192.98 1541481.5 1631438.0 26743551 100 c
neval 0 1.0 18.88 1.0 1.0 303 100 a