我正在尝试创建一个参考列表,这样当我遇到名字时,我就可以为其分配一个性别。完全准确性并不重要。
我在此表格中列出了社会安全管理局的姓名,相应性别和姓名/性别对的列表:
Name Gender Count
Aaron F 10
Aaron M 7246
Abbie F 242
Abbie M 8
可以说,数据中有许多男女皆宜的名字。当名字是男性和女性时,我想摆脱罕见的名字/性别对。
我总是转向dplyr这样的问题,我知道我可以过滤绝对值,例如当count> 100.但是,我不想过滤掉罕见的名字,就像那个罕见的名字/性别对比其他名字/性别对小得多。
如何编写代码来完成以下任务:
filter x when Name=Name and Count < 10*Count
编辑:感谢帮助人员。我意识到我在最初的帖子中不清楚。
我希望能够拥有一个我相对确定性别的名字记录。 (例如,上面例子中的Aaron将具有Gender = M)。这就是为什么我想创建一个过滤规则,如果一个性别/名称对的计数是另一个性别/名称对的10倍。但是,如果计数很接近,我会将此性别指定为男女皆宜的U,因为我们在为此名称指定性别方面并不积极。 (不担心保留正确的计数值。)
预期输出将是这样的:
Name Gender Count
Aaron M 7246
Abbie F 242
Alva U 150
答案 0 :(得分:1)
你没有提供一个非常有用的数据集,所以我做了一个新的:
library(dplyr)
library(randomNames)
set.seed(2)
randomize.gender <- function(x) {
sapply(x, function(y) {
c(y, "Male","Female")[sample(1:3,1,prob=c(.82,.09,.09))]
})
}
df <- data.frame(Name=randomNames(n=10,
gender=c("Male","Female"),
which.names="first"),
Gender=c("Male","Female"),
stringsAsFactors = FALSE) %>%
sample_n(1000,replace=TRUE) %>%
mutate(Gender = randomize.gender(Gender))
Name Gender
1 Brianne Female
2 Julia Female
3 Kelsey Female
4 Claude Male
5 Cameron Male
6 Nathan Male
7 Claude Male
8 Nathan Male
9 Kelsey Female
10 Kelsey Female
.. ... ...
要解决您的问题,首先需要一个函数来根据观察到的性别比例确定最常用的性别:
determine.gender <- function(x) {
sapply(x, function(y) {
# prop.F is the proportion of instances that a name is female
cutoff.ratio <- 1/10
if(y < cutoff.ratio) {
"Male"
} else if(y >= 1-cutoff.ratio) {
"Female"
} else {
"Unisex"
}
})
}
然后你可以使用一点dplyr和tidyr魔法来获得你的解决方案
df %>%
group_by(Name) %>%
count(Name,Gender) %>%
spread(Gender, n) %>%
mutate(prop.F = Female/(Female+Male)) %>%
mutate(likely.gender = determine.gender(prop.F))
Name Female Male prop.F likely.gender
1 Brianne 80 8 0.9090909 Female
2 Cameron 12 86 0.1224490 Unisex
3 Claude 5 95 0.0500000 Male
4 Isabella 88 11 0.8888889 Unisex
5 Julia 84 7 0.9230769 Female
6 Kelsey 86 6 0.9347826 Female
7 Linda 98 11 0.8990826 Unisex
8 Nathan 14 88 0.1372549 Unisex
9 William 12 94 0.1132075 Unisex
10 Zamir 15 100 0.1304348 Unisex
答案 1 :(得分:0)
根据编辑过的帖子,我们可以创建一个逻辑功能(&#34; f1&#34;,&#34; f2&#34;),按&#34; Name&#34;对数据进行分组,替换&#34;性别&#34;中的元素和&#34;伯爵&#34; by&#34; U&#34;和#34; Count&#34;的第一个值(按组)即Count[1L]
,如果所有元素都在&#34; Count&#34;基于&#34; f1&#34;为TRUE。获取unique
行,filter
行(filter(f1(Count))
)
library(dplyr)
f1 <- function(x,y) x*10 > max(x) & n_distinct(y) >1
f2 <- function(x) x*10 > max(x)
df %>%
group_by(Name) %>%
mutate(GenderN=replace(Gender, all(f1(Count, Gender)), 'U'),
Count=replace(Count, all(f1(Count, Gender)), Count[1L])) %>%
select(-Gender)%>%
rename(Gender=GenderN)%>%
unique() %>%
filter(f2(Count))
# Name Count Gender
#1 Aaron 7246 M
#2 Abbie 242 F
#3 Alva 150 U
#4 Amy 180 F
#5 Benson 120 M
或者使用data.table
,我们可以转换&#34; data.frame&#34;到&#34; data.table&#34; (setDT(df)
)。如果&#34;计数&#34;中的所有元素按组(&#34;名称&#34;)根据功能(&#34; f1&#34;)为TRUE,替换&#34;性别&#34;,&#34;计数&#34;元素(即&#34; U&#34;,&#34的第一个值; Count&#34;)或者返回data.table(.SD
)的子集并在&#34;上应用函数。计数&#34;该子集中的列用于过滤行。 (.SD[f1(Count)]
)
library(data.table)
f1 <- function(x,y) x*10 > max(x) & uniqueN(y) >1
setDT(df)[, if(all(f1(Count, Gender))) list(Gender='U',
Count=Count[1L]) else .SD[f2(Count)], Name]
# Name Gender Count
#1: Aaron M 7246
#2: Abbie F 242
#3: Alva U 150
#4: Amy F 180
#5: Benson M 120
如果你需要&#34; Unisex&#34;的所有行。而不是上述内容,请将Count[1L]
替换为Count
setDT(df)[, if(all(f1(Count, Gender))) list(Gender='U', Count=Count)
else .SD[f2(Count)], Name]
# Name Gender Count
#1: Aaron M 7246
#2: Abbie F 242
#3: Alva U 150
#4: Alva U 170
#5: Amy F 180
#6: Benson M 120
df <- structure(list(Name = c("Aaron", "Aaron", "Abbie", "Abbie", "Alva",
"Alva", "Amy", "Benson"), Gender = c("F", "M", "F", "M", "M",
"F", "F", "M"), Count = c(10L, 7246L, 242L, 8L, 150L, 170L, 180L,
120L)), .Names = c("Name", "Gender", "Count"), class = "data.frame", row.names = c("1",
"2", "3", "4", "5", "6", "7", "8"))