Skip to content

PERF: Faster CategoricalIndex from categorical #17513

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

TomAugspurger
Copy link
Contributor

Master:

In [1]: import pandas as pd; import numpy as np

In [2]: arr = ['s%04d' % i for i in np.random.randint(0, 500000 // 10, size=500000)]; s = pd.Series(arr).astype('category')

In [3]: %timeit pd.CategoricalIndex(s)
69.4 ms ± 946 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

HEAD

In [1]: import pandas as pd; import numpy as np

In [2]: arr = ['s%04d' % i for i in np.random.randint(0, 500000 // 10, size=500000)]; s = pd.Series(arr).astype('category')

In [3]: %timeit pd.CategoricalIndex(s)
9.06 µs ± 182 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Is that a 7000x speedup, or did I mess up the math?

@TomAugspurger TomAugspurger added Categorical Categorical Data Type Performance Memory or execution speed performance labels Sep 13, 2017
@codecov
Copy link

codecov bot commented Sep 13, 2017

Codecov Report

Merging #17513 into master will decrease coverage by 0.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #17513      +/-   ##
==========================================
- Coverage   91.22%    91.2%   -0.02%     
==========================================
  Files         163      163              
  Lines       49586    49588       +2     
==========================================
- Hits        45233    45227       -6     
- Misses       4353     4361       +8
Flag Coverage Δ
#multiple 88.99% <100%> (ø) ⬆️
#single 40.2% <50%> (-0.07%) ⬇️
Impacted Files Coverage Δ
pandas/core/indexes/category.py 98.55% <100%> (ø) ⬆️
pandas/io/gbq.py 25% <0%> (-58.34%) ⬇️
pandas/core/frame.py 97.77% <0%> (-0.1%) ⬇️
pandas/core/indexes/datetimes.py 95.53% <0%> (+0.09%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0097cb7...7cad4f8. Read the comment docs.

@@ -130,6 +130,9 @@ def _create_categorical(self, data, categories=None, ordered=None):
-------
Categorical
"""
if isinstance(data, ABCSeries) and is_categorical_dtype(data):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The isinstance(data, ABCSeries) is maybe a bit too restrictive. This rules out, e.g. CategoricalIndex. But at moment the CategoricalIndex constructor takes a different (faster) path, so it wouldn't benefit from this change anyway.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, does it still pass if you add ABCCategoricalIndex here as well? it is more consistent

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about isinstance(data, (ABCSeries, type(self))). That'll catch Series(dtype='category'), and CategoricalIndex, but not Categorical.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about (is_categorical_dtype and not ABCCategorical)?

maybe add a helper method

_ensure_categorical ?

which passes thru Categorical
does .values on CI and Series
and raises else

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe add a helper method

I'd prefer to wait till we need that. I haven't come across any other cases where I need to treat CategoricalIndex and Series(dtype=category) differently than Categorical.

@topper-123
Copy link
Contributor

I am able to replicate this result (159 ms -> 9.88 µs).

@TomAugspurger TomAugspurger force-pushed the ci-ctor-from-categorical branch from d77b095 to 7cad4f8 Compare September 14, 2017 16:26
@jreback jreback added this to the 0.21.0 milestone Sep 14, 2017
@jreback
Copy link
Contributor

jreback commented Sep 14, 2017

lgtm. merge on green.

@TomAugspurger
Copy link
Contributor Author

Unrelated test failure https://travis-ci.org/pandas-dev/pandas/jobs/275540546#L1608 (already an issue at #17510)

@TomAugspurger TomAugspurger merged commit 94266d4 into pandas-dev:master Sep 14, 2017
@TomAugspurger TomAugspurger deleted the ci-ctor-from-categorical branch September 14, 2017 23:29
alanbato pushed a commit to alanbato/pandas that referenced this pull request Nov 10, 2017
No-Stream pushed a commit to No-Stream/pandas that referenced this pull request Nov 28, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Categorical Categorical Data Type Performance Memory or execution speed performance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants