# \[RFC\] GenderInference.jl

**URL:** https://discourse.julialang.org/t/rfc-genderinference-jl/22294
**Category:** Data
**Tags:** diversity
**Created:** [March 25, 2019, 9:49am UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294 "2019-03-25T09:49:47Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)
#### Post date: [March 25, 2019, 9:49am UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/1 "2019-03-25T09:49:47Z")

</div>

I made a little package, [GenderInference.jl](https://github.com/kescobo/GenderInference.jl), that’ similar to [`Gender`](https://www.r-project.org/nosvn/pandoc/gender.html) in R and [`SexMachine`](https://pypi.org/project/SexMachine/) in python. Basically, you give a first name, and it guesses the gender:

```julia
julia> using GenderInference

julia> gender("Kevin")
:male

```

You can also ask look at a specific year or years, get raw counts and percentages.

```julia
julia> gendercount("stefan", 1976:2002)
(female = 42, male = 11217)

julia> percentfemale("jeff")
0.002147423092289253

```

I haven’t registered it yet, but I’d love thoughts on the API and especially my handling of when data isn’t available. I’ve only got data for 1880-2017, so what happens when you ask for dates outside that range? I’ve opted to use `missing` in most cases

```julia
julia> gendercount("jane", 1880:1900)
(female = 7348, male = 0)

julia> gendercount("jane", 1879:1900)
(female = missing, male = missing)

```

If you ask for a name that doesn’t have any entries, but in a year that’s in range, `gendercount()` gives zeros but tthe `percent{female/male}()` functions give `missing`. Does that make sense/seem intuitive?

```julia
julia> gendercount("Viral")
(female = 0, male = 63)

julia> gendercount("Viral", 1980)
(female = 0, male = 0)

julia> percentmale("Viral")
1.0

julia> percentmale("Viral", 1980)
missing

```

Since I’ve never studied data structures and algorithms, there’s probably a lot to be desired with respect to how I’m building, storing, and accessing the data, so any comments/suggestions there would also be most welcome. Thanks!

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [March 25, 2019, 9:58am UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/2 "2019-03-25T09:58:38Z")

</div>

Cool!

I made a very similar package.

> **[GitHub - JuliaText/NameToGender.jl: Guess gender based on first name](https://github.com/JuliaText/NameToGender.jl)**
>
> Guess gender based on first name. Contribute to JuliaText/NameToGender.jl development by creating an account on GitHub.

but based probably on worse data, it doesn’t have count or percenage just 5 categories, and it is old.  
Also NameToGender is a near direct port of SexMachine, so it is GPL, which I do not like.

The best data I am aware of is discussed in:

> <https://github.com/JuliaText/NameToGender.jl/issues/2#issuecomment-396473119>
>
> This is more of feedback than an issue, not sure its actionable. 
> 
> I tried thi…s on a real world list of almost 18K names, and got a hit rate of around 34%.

I think it is important to allow to be parameterized by country.

> If you ask for a name that doesn’t have any entries, but in a year that’s in range, `gendercount()` gives zeros but tthe `percent{female/male}()` functions give `missing` . Does that make sense/seem intuitive?

Yes, that is what NameToGender.jl does

---

<div class="post-metadata">

### Author: ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)
#### Post date: [March 25, 2019, 10:15am UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/3 "2019-03-25T10:15:54Z")

</div>

> [@oxinabox](#):
>
> I made a very similar package.

Oof! Sorry for not seeing that. I did a bit of searching a couple of months ago and didn’t see it. Do you think it makes sense to combine somehow?

> [@oxinabox](#):
>
> The best data I am aware of is discussed in…

Neat. The R package mentions [this dataset](http://www.cs.cmu.edu/afs/cs/project/ai-repository/ai/areas/nlp/corpora/names/0.html) which is also just male/female without counts, and I was thinking of falling back to that list if no count data is available. And I’m already doing case-insensitive matching so that’s no big deal.

> [@oxinabox](#):
>
> I think it is important to allow to be parameterized by country.

Totally agree. `Gender` also does this, though the package README only seems to list US sources of data. I see you linked a couple of other country sources in that issue - I suppose that’s a start.

I also don’t currently support letters other than `A-Za-z`. Eg.

```julia
julia> gendercount("jose")
(female = 4166, male = 560679)

julia> gendercount("josé")
(female = 0, male = 0)

```

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 25, 2019, 10:38am UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/4 "2019-03-25T10:38:43Z")

</div>

This looks like a thin wrapper for accessing a particular database, ie the frequency count of various names (grouped by gender, year, and potentially country). I wonder if it would not be better to

1. cooperate on the database itself, sharing it between various languages,
2. dumping it in a common format (CSV comes to mind),
3. just using standard, existing tools loading and lookup.

---

<div class="post-metadata">

### Author: ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)
#### Post date: [March 25, 2019, 10:59am UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/5 "2019-03-25T10:59:30Z")

</div>

> [@Tamas\_Papp](#):
>
> This looks like a thin wrapper for accessing a particular database

Essentially, yes. At the moment, there’s only one data source, and it’s already in CSV format (though separated by year rather than name)

> [@Tamas\_Papp](#):
>
> cooperate on the database itself, sharing it between various languages,

A bunch of packages already use this data source - it’s the US social security administration. I’d be surprised if they want to do more than they’re already doing, but the data is in really good shape - I essentially parsed the csvs and made a dictionary.

> [@Tamas\_Papp](#):
>
> 1. dumping it in a common format (CSV comes to mind),

At the moment, this doesn’t make sense because as I said it’s already in that form at the SSA. But I think that if I start combining a bunch of sources, then you’re right that it would probably be worth building a package that just pulls them all together and spits them out in a uniform way.

> [@Tamas\_Papp](#):
>
> 1. just using standard, existing tools loading and lookup.

I didn’t actually benchmark, though I assume that filtering a dataframe on a given name is slower than dictionary lookup. I’m going to be using this to look at a dataset of a few hundred thousand names, so taking the time to construct the dictionary seemed worth the cost. I definitely could be wrong though.

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 25, 2019, 11:06am UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/6 "2019-03-25T11:06:49Z")

</div>

> [@kevbonham](#):
>
> taking the time to construct the dictionary seemed worth the cost

No argument there, but creating a fast lookup table (eg as a `Dict`) is a one-liner and I am not sure this calls for a package.

---

<div class="post-metadata">

### Author: ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)
#### Post date: [March 25, 2019, 12:40pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/7 "2019-03-25T12:40:15Z")

</div>

Oh, I see. Maybe not, but this is more or less just a slightly more polished version of code I was working anyway, and other languages have packages like this. 🤷‍♂️

Is there a concern about having a package, or are you just thinking about where effort is best spent?

---

<div class="post-metadata">

### Author: ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)
#### Post date: [March 25, 2019, 12:53pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/8 "2019-03-25T12:53:34Z")

</div>

> [@kevbonham](#):
>
> Is there a concern about having a package, or are you just thinking about where effort is best spent?

I would just curate the _data_ somehow, and use the standard tools (eg CSV reader packages, DataFrame and similar for manipulation, the built-in `Dict` implementation). This way I would benefit from improvements of the latter, and keep things more flexible: most possible groupings and queries can be implemented in under 5 lines even with the `Dict` construction thrown in.

But that is just my opinion, if you prefer a package for this then that’s fine.

---

<div class="post-metadata">

### Author: ![davidbp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/davidbp/32/463_2.png) [@davidbp](https://discourse.julialang.org/u/davidbp)
#### Post date: [March 25, 2019, 1:22pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/9 "2019-03-25T13:22:38Z")

</div>

Maybe building a character model instead of a simple lookup would add more value to the project since it could generalise to misspelled names (or even unseen names).

Is there any NER package available in julia?  
There are several problems with names that are made up with 2 words (at least in Spanish). “Jose Maria” is a male name but “Maria” is a female name.

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [March 25, 2019, 2:05pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/10 "2019-03-25T14:05:48Z")

</div>

> [@kevbonham](#):
>
> Oof! Sorry for not seeing that. I did a bit of searching a couple of months ago and didn’t see it. Do you think it makes sense to combine somehow?

I think it makes sense to deprecate mine for yours.  
Particularly if you add country and more up to date data.

> [@Tamas\_Papp](#):
>
> This looks like a thin wrapper for accessing a particular database, ie the frequency count of various names (grouped by gender, year, and potentially country). I wonder if it would not be better to

This is useful.  
Small packages are useful.  
Low effort to mainain.  
Extensible.

It is a nontrivial wrapper because it handles missings and percentiles.

I guess one could create a TabularDataSource that abstracts around this general notion.  
but it seems over engineered when no other usecase has shown up.

---

<div class="post-metadata">

### Author: ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)
#### Post date: [March 25, 2019, 6:15pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/11 "2019-03-25T18:15:43Z")

</div>

> [@oxinabox](#):
>
> I think it makes sense to deprecate mine for yours.  
> Particularly if you add country and more up to date data.

Ok, I’m fine with this. Would you want to pull it into the same org or let it be free-standing?

---

<div class="post-metadata">

### Author: ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)
#### Post date: [March 25, 2019, 6:16pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/12 "2019-03-25T18:16:58Z")

</div>

Considering I’m not really sure what you mean by character model, I think this is beyond my abilities :-). Happy to accept a PR though

---

<div class="post-metadata">

### Author: ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)
#### Post date: [March 25, 2019, 9:19pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/13 "2019-03-25T21:19:54Z")

</div>

I think JuliaText is a good place for it, but no rush, nor nescesity

> Considering I’m not really sure what you mean by character model, I think this is beyond my abilities :-). Happy to accept a PR though

And this is why JuliaText is a good place for it.

---

<div class="post-metadata">

### Author: ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)
#### Post date: [March 26, 2019, 2:47pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/14 "2019-03-26T14:47:39Z")

</div>

> [@oxinabox](#):
>
> I think JuliaText is a good place for it, but no rush, nor nescesity

I’m happy to do this, and it probably makes sense to do before registering. Someone on slack suggested the name could be clearer - any thoughts on that?

---

<div class="post-metadata">

### Author: ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)
#### Post date: [March 26, 2019, 3:12pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/15 "2019-03-26T15:12:18Z")

</div>

I tried to install the package, but after issuing `using GenderInference` I see thousands of lines like this:

```julia
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]
Do you want to download the dataset from https://www.ssa.gov/oact/babynames/names.zip to "/home/mose/.julia/datadeps/US Census - names"?
[y/n]

```

and seems to be stuck in an infinite loop that I can’t stop unless I forcibly kill Julia from the outside (Ctrl + C doesn’t even work).

Is this the expected behaviour?

---

<div class="post-metadata">

### Author: ![kevbonham](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kevbonham/32/216165_2.png) [@kevbonham](https://discourse.julialang.org/u/kevbonham)
#### Post date: [March 26, 2019, 3:21pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/16 "2019-03-26T15:21:36Z")

</div>

> [@giordano](#):
>
> Is this the expected behaviour?

Yikes! Definitely not. That’s a message from DataDeps.jl, but you should only get it once. I’ll take a look when I get home, but this was not happening on my system (and the tests pass on a fresh environment so…)

---

<div class="post-metadata">

### Author: ![giordano](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/giordano/32/2166_2.png) [@giordano](https://discourse.julialang.org/u/giordano)
#### Post date: [March 26, 2019, 3:28pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/17 "2019-03-26T15:28:27Z")

</div>

I can reproduce the error also in an empty project to which I added only this package:

```julia
julia --project=/tmp
               _
   _ _ _(_)_ | Documentation: https://docs.julialang.org
  (_) | (_) (_) |
   _ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _ | |
  | | |_| | | | (_| | | Version 1.1.0 (2019-01-21)
 _/ |\ __'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |

(tmp) pkg> status
    Status `/tmp/Project.toml`
  [d768500e] GenderInference v0.0.0 #master (https://github.com/kescobo/GenderInference.jl)

```

---

<div class="post-metadata">

### Author: ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)
#### Post date: [March 26, 2019, 5:15pm UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/18 "2019-03-26T17:15:38Z")

</div>

> [@kevbonham](#):
>
> julia\> gendercount(“Viral”) (female = 0, male = 63) julia\> gendercount(“Viral”, 1980) (female = 0, male = 0) julia\> percentmale(“Viral”) 1.0

Shouldn’t `percentmale` be 100.0 here? Alternatively, the name could be `fractionmale`.

---

<div class="post-metadata">

### Author: ![dellison](https://avatars.discourse-cdn.com/v4/letter/d/ce73a5/32.png) [@dellison](https://discourse.julialang.org/u/dellison)
#### Post date: [March 27, 2019, 3:36am UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/19 "2019-03-27T03:36:59Z")

</div>

I can reproduce @giordano’s issue, but I have some suggestions for fixing it. 🙂

I took a quick look at the code, and to me it looks like your use of `datadep"US Census - names"` [here](https://github.com/kescobo/GenderInference.jl/blob/master/src/data_management.jl#L70) means that julia will try to (down)load the whole dataset at package precompilation time to calculate the value of the const `NAMES`. You can fix this by putting ` __precompile__ (false)` at the very top of the module file (see [docs](https://docs.julialang.org/en/v1/manual/modules/index.html#Module-initialization-and-precompilation-1)), or by restructuring the code so that it doesn’t need to download the dataset to precompile. (Either way, it might also be [a good idea](http://white.ucc.asn.au/DataDeps.jl/stable/z20-for-pkg-devs.html#Registering-a-DataDep-1) to have the `register(DataDep(...))` happen inside an ` __init__ ()`).

If you don’t mind another kind of feedback (regarding the package’s name): even if it’s a mathematically appropriate term for statistical inference, it seems to me that providing code to “infer” a binary gender from surface features (i.e., a person’s name) could be seen as assuming some specific political ideas about gender, even if you don’t mean it that way.

---

<div class="post-metadata">

### Author: ![bennedich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bennedich/32/4894_2.png) [@bennedich](https://discourse.julialang.org/u/bennedich)
#### Post date: [March 27, 2019, 7:27am UTC](https://discourse.julialang.org/t/rfc-genderinference-jl/22294/20 "2019-03-27T07:27:47Z")

</div>

Nice work! I think it’s super useful to have this data readily available as a package in Julia. Some feedback below.

* * *
How about exposing the raw data through your package? I've done a project in the past where I used this data, but what I needed then was a list of the most common names per year, not to do lookups for specific names. I realize that this is not the point of your package, but it seems like it would be easy to expose, and could increase the usefulness of your package (perhaps it's already exposed but I couldn't find it in the README?)
* * *
For faster support of range queries, the data structure I'd choose for this is not a dictionary of year -\> count, but a cumulative array of counts. Then, when you want to calculate the counts for a range like 1900 to 2000, the calculation would simply be:

```julia
name_counts = counts["Kevin"]
count = name_counts[2000 + 1 - START_YEAR] - name_counts[1900 - START_YEAR]

```

For consecutive range queries, this reduces the complexity from linear time in range size to constant. It makes lookups for single years slightly slower however, since you’d need to do a subtraction (but still LOTS faster than using a dictionary). If you wish to avoid that, you could keep an array with raw counts per year as well.

Also, if space is an issue, consider not using 64 bit ints for the counts. 32 bits should probably suffice.

* * *
I would be more clear about the fact that this is only valid for US names. By stating:

> “A package to infer a person’s gender based on…”

in the opinion of a non-American, this plays on the stereotype that Americans are unaware that there are other countries out there than the US. Perhaps more appropriate would be something like:

> “A package to infer an American’s gender based on…”

🙂

* * *

```julia
percentfemale("Kristofer", 2019)

```

Since you are using the names of other prolific Julia contributors, I’m wondering if this should be “Kristoffer”? 🙂 (Unlike the US, this name is usually spelled with two "f"s in Sweden.)

[Next page](https://discourse.julialang.org/t/rfc-genderinference-jl/22294.md?page=2)
