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

Allow indices to be mapped through through dictionaries or series #15081

Merged
merged 22 commits into from Nov 25, 2017

Conversation

Projects
None yet
5 participants
@nateyoder
Contributor

nateyoder commented Jan 8, 2017

  • closes #12756
  • tests added / passed
  • passes git diff upstream/master | flake8 --diff
  • whatsnew entry
@@ -2395,6 +2394,25 @@ def get_indexer_for(self, target, **kwargs):
indexer, _ = self.get_indexer_non_unique(target, **kwargs)
return indexer
def get_values_from_dict(self, input_dict):

This comment has been minimized.

@jreback

jreback Jan 9, 2017

Contributor

make this a private function (_get_values.....)

Parameters
----------
input_dict : dict

This comment has been minimized.

@jreback

jreback Jan 9, 2017

Contributor

call this data

Returns
-------
Union[np.array, list]

This comment has been minimized.

@jreback

jreback Jan 9, 2017

Contributor

this should always return np.ndarray no?

@@ -2438,8 +2456,8 @@ def map(self, mapper):
Parameters
----------
mapper : callable
Function to be applied.
mapper : Union[function, dict, Series]

This comment has been minimized.

@jreback

jreback Jan 9, 2017

Contributor

use {callable, dict, Series}

This comment has been minimized.

@jreback

jreback Jan 9, 2017

Contributor

say new in 0.20.0 for (dict/Series)

@@ -2450,7 +2468,18 @@ def map(self, mapper):
"""
from .multi import MultiIndex
mapped_values = self._arrmap(self.values, mapper)
if isinstance(mapper, ABCSeries):

This comment has been minimized.

@jreback

jreback Jan 9, 2017

Contributor

for a dict, why can' you just Series(data) then treat it like a Series?

This comment has been minimized.

@jreback

jreback Jan 22, 2017

Contributor

?

This comment has been minimized.

@jreback

jreback Jan 22, 2017

Contributor

so I think its worth the effort to combine this code with Series.map (in reality you can prob just move the Series.map code to core.base.Base I think (with maybe some modifications here).

def get_values_from_dict(self, input_dict):
"""Return the values of the input dictionary in the order the keys are
in the index. np.nan is returned for index values not in the
dictionary.

This comment has been minimized.

@jreback

jreback Jan 9, 2017

Contributor

same doc-string

Returns
-------
Union[np.array, list]

This comment has been minimized.

@jreback

jreback Jan 9, 2017

Contributor

I think you can move this to tseries.common, then for the DatetimeIndex you do a super call (e.g. with the dict_compat)

@@ -3511,6 +3511,10 @@ def test_map(self):
result = index.map(lambda x: x + 1)
expected = index + 1
tm.assert_index_equal(result, expected)
series_map = pd.Series(expected, index)
tm.assert_index_equal(index.map(series_map), expected)

This comment has been minimized.

@jreback

jreback Jan 9, 2017

Contributor

try with an empty, try with some NaT's

rng = timedelta_range('1 day', periods=10)
f = lambda x: x.days
result = rng.map(f)
exp = Int64Index([f(x) for x in rng])
tm.assert_index_equal(result, exp)
s = Series(exp, index=rng)

This comment has been minimized.

@jreback

jreback Jan 9, 2017

Contributor

sam as above (you might wish to move these tests to test_datetimelike to avoid duplication)

exp_values = [f(x) for x in rng]
exp = Index(exp_values, dtype='<U8')
tm.assert_index_equal(rng.map(f), exp)

This comment has been minimized.

@jreback

jreback Jan 9, 2017

Contributor

test for empty

@jreback

This comment has been minimized.

Contributor

jreback commented Jan 21, 2017

can you rebase / update

@codecov-io

This comment has been minimized.

codecov-io commented Jan 22, 2017

Codecov Report

Merging #15081 into master will decrease coverage by 0.02%.
The diff coverage is 91.78%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master   #15081      +/-   ##
==========================================
- Coverage   91.34%   91.31%   -0.03%     
==========================================
  Files         163      163              
  Lines       49717    49742      +25     
==========================================
+ Hits        45413    45424      +11     
- Misses       4304     4318      +14
Flag Coverage Δ
#multiple 89.11% <91.78%> (-0.01%) ⬇️
#single 40.5% <42.46%> (-0.07%) ⬇️
Impacted Files Coverage Δ
pandas/core/series.py 94.76% <100%> (-0.08%) ⬇️
pandas/core/indexes/datetimes.py 95.51% <100%> (+0.02%) ⬆️
pandas/core/dtypes/missing.py 90.24% <75%> (-0.5%) ⬇️
pandas/core/indexes/datetimelike.py 96.91% <83.33%> (-0.2%) ⬇️
pandas/core/dtypes/cast.py 88.52% <85.71%> (-0.08%) ⬇️
pandas/core/indexes/base.py 96.39% <92.3%> (-0.04%) ⬇️
pandas/core/base.py 96.54% <96.29%> (-0.03%) ⬇️
pandas/io/gbq.py 25% <0%> (-58.34%) ⬇️
pandas/core/frame.py 97.8% <0%> (-0.1%) ⬇️

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 412988e...dd0b7e9. Read the comment docs.

@nateyoder

This comment has been minimized.

Contributor

nateyoder commented Jan 22, 2017

Hi @jreback sorry for the delay. Work got a little crazy. Let me know what other changes you'd like to see made.

@jreback jreback changed the title from Allow indeices to be mapped through through dictionaries or series to Allow indices to be mapped through through dictionaries or series Jan 22, 2017

@@ -139,6 +139,8 @@ Other enhancements
- ``pd.merge_asof()`` gained the option ``direction='backward'|'forward'|'nearest'`` (:issue:`14887`)
- ``Series/DataFrame.asfreq()`` have gained a ``fill_value`` parameter, to fill missing values (:issue:`3715`).
- ``Series/DataFrame.resample.asfreq`` have gained a ``fill_value`` parameter, to fill missing values during resampling (:issue:`3715`).
- ``Index.map`` can now accept series and dictionary input object.

This comment has been minimized.

@jreback

jreback Jan 22, 2017

Contributor

add the issue number

@@ -2450,7 +2468,18 @@ def map(self, mapper):
"""
from .multi import MultiIndex
mapped_values = self._arrmap(self.values, mapper)
if isinstance(mapper, ABCSeries):

This comment has been minimized.

@jreback

jreback Jan 22, 2017

Contributor

?

@@ -2450,7 +2468,18 @@ def map(self, mapper):
"""
from .multi import MultiIndex
mapped_values = self._arrmap(self.values, mapper)
if isinstance(mapper, ABCSeries):

This comment has been minimized.

@jreback

jreback Jan 22, 2017

Contributor

so I think its worth the effort to combine this code with Series.map (in reality you can prob just move the Series.map code to core.base.Base I think (with maybe some modifications here).

@jreback

This comment has been minimized.

Contributor

jreback commented Mar 20, 2017

@nateyoder this was quite close. can you rebase / update and we can get it in?

@nateyoder

This comment has been minimized.

Contributor

nateyoder commented Mar 30, 2017

Hi Jeff, My apologies as work has swamped me again. I'll try to get everything up to date and working again this weekend and you can let me know if there are other changes you'd like. Thanks for your patience.

@jreback

This comment has been minimized.

Contributor

jreback commented Mar 30, 2017

@nateyoder great thanks. yeah when you rebase will take another look. feel free to ping.

@jreback

This comment has been minimized.

Contributor

jreback commented Apr 18, 2017

can you rebase / update

@nateyoder

This comment has been minimized.

Contributor

nateyoder commented Apr 22, 2017

Hi @jreback. Apologies again on the delay. I updated the tests to include some of the missing cases but was a little unsure how to re-use the mapping code from series like you had suggested.

@nateyoder

This comment has been minimized.

Contributor

nateyoder commented Apr 23, 2017

I took a shot at combining the code but in at least my current implementation I still had to do some object specific code. If you've got a better idea let me know and I'll be happy to take a look.

I also took this opportunity to not create a series from a dict but instead use an index directly which as you can see from the below ASV results provided a slight but pretty consistent performance improvement for dicts and didn't significantly slow down series maps:

asv continuous -f 1.1 upstream/master HEAD -b ^series_methods.series_map -E conda:2.7
· Creating environments
· Discovering benchmarks
·· Uninstalling from conda-py2.7-Cython-matplotlib-numexpr-numpy-openpyxl-pytables-pytest-scipy-sqlalchemy-xlrd-xlsxwriter-xlwt
·· Installing into conda-py2.7-Cython-matplotlib-numexpr-numpy-openpyxl-pytables-pytest-scipy-sqlalchemy-xlrd-xlsxwriter-xlwt..
· Running 4 total benchmarks (2 commits * 1 environments * 2 benchmarks)
[  0.00%] · For pandas commit hash 99e11b4b:
[  0.00%] ·· Building for conda-py2.7-Cython-matplotlib-numexpr-numpy-openpyxl-pytables-pytest-scipy-sqlalchemy-xlrd-xlsxwriter-xlwt.......................................
[  0.00%] ·· Benchmarking conda-py2.7-Cython-matplotlib-numexpr-numpy-openpyxl-pytables-pytest-scipy-sqlalchemy-xlrd-xlsxwriter-xlwt
[ 25.00%] ··· Running series_methods.series_map_dict.time_series_map_dict              1.61±0.03ms
[ 50.00%] ··· Running series_methods.series_map_series.time_series_map_series             995±20μs
[ 50.00%] · For pandas commit hash 19fc8dac:
[ 50.00%] ·· Building for conda-py2.7-Cython-matplotlib-numexpr-numpy-openpyxl-pytables-pytest-scipy-sqlalchemy-xlrd-xlsxwriter-xlwt...
[ 50.00%] ·· Benchmarking conda-py2.7-Cython-matplotlib-numexpr-numpy-openpyxl-pytables-pytest-scipy-sqlalchemy-xlrd-xlsxwriter-xlwt
[ 75.00%] ··· Running series_methods.series_map_dict.time_series_map_dict              2.10±0.09ms
[100.00%] ··· Running series_methods.series_map_series.time_series_map_series             970±60μs       before           after         ratio
     [19fc8dac]       [99e11b4b]
-     2.10±0.09ms      1.61±0.03ms     0.77  series_methods.series_map_dict.time_series_map_dict

SOME BENCHMARKS HAVE CHANGED SIGNIFICANTLY.

EDIT: Note that give that the above method did NOT work in both 2.7 and 3 this performance improvement was reverted and the included changes did not significantly change performance.

@nateyoder

This comment has been minimized.

Contributor

nateyoder commented Apr 23, 2017

Sorry didn't test with 2.7. I'll go back to just using series even though its a little slower.

@nateyoder

This comment has been minimized.

Contributor

nateyoder commented Apr 23, 2017

Sorry for the trashing around. I wasn't familiar with what should be an index vs a multi-index in mapping with a dictionary made of tuples. I ended up just going back to using a series because I couldn't keep the performance going straight through the _ensure_index function.

@@ -521,6 +521,7 @@ Other Enhancements
- The ``display.show_dimensions`` option can now also be used to specify
whether the length of a ``Series`` should be shown in its repr (:issue:`7117`).
- ``parallel_coordinates()`` has gained a ``sort_labels`` keyword arg that sorts class labels and the colours assigned to them (:issue:`15908`)

This comment has been minimized.

@jreback

jreback Apr 25, 2017

Contributor

remove for now. This will be in 0.21.0 (though file doesn't exist yet, don't create it).

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

Removed

@@ -8,10 +8,10 @@
from pandas.core.dtypes.missing import isnull
from pandas.core.dtypes.generic import ABCDataFrame, ABCSeries, ABCIndexClass
from pandas.core.dtypes.common import is_object_dtype, is_list_like, is_scalar
from pandas.core.dtypes.common import is_object_dtype, is_list_like, is_scalar, is_extension_type

This comment has been minimized.

@jreback

jreback Apr 25, 2017

Contributor

this causes lint issues, use parens.

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

👍

@@ -933,6 +933,44 @@ def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
klass=self.__class__.__name__, op=name))
return func(**kwds)
def _map_values(self, values, arg, na_action=None):
if is_extension_type(self.dtype):

This comment has been minimized.

@jreback

jreback Apr 25, 2017

Contributor

can you add a doc-string

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

👍

Parameters
----------
data : {dict, DictWithoutMissing}

This comment has been minimized.

@jreback

jreback Apr 25, 2017

Contributor

just dict

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

👍

@@ -2706,31 +2726,36 @@ def groupby(self, values):
return result
def map(self, mapper):
"""Apply mapper function to an index.
def map(self, arg, na_action=None):

This comment has been minimized.

@jreback

jreback Apr 25, 2017

Contributor

technically need to deprecate and rename mapper -> arg add a versionadded (0.21.0) for na_action.

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

Is this something I need to do? If so can you show me how you've done this in the past? Otherwise should I just change arg -> mapper?

tm.assert_index_equal(self.index.map(dict_map), expected)
# empty mappable
nan_index = Index([pd.np.nan] * len(self.index))

This comment has been minimized.

@jreback

jreback Apr 25, 2017

Contributor

use np.nan

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

👍

result = self.index.map(lambda x: pd.NaT if x == self.index[0] else x)
expected = Index([pd.NaT] + self.index[1:].tolist())
tm.assert_index_equal(result, expected)
series_map = pd.Series(expected, self.index)

This comment has been minimized.

@jreback

jreback Apr 25, 2017

Contributor

blank line between cases

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

👍

index = PeriodIndex([2005, 2007, 2009], freq='A')
result = index.map(lambda x: x + 1)

This comment has been minimized.

@jreback

jreback Apr 25, 2017

Contributor

what does this do now, raise? put a test for that

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

No it still works. I understood from your previous comment on Jan 9th that I could move it to test_datetimelike but have since tested using them using pandas/tests/indexes/datetimelike.py

@@ -74,3 +74,29 @@ def test_union(self):
for case in cases:
result = first.union(case)
self.assertTrue(tm.equalContents(result, everything))

This comment has been minimized.

@jreback

jreback Apr 25, 2017

Contributor

ideally could push some of these (NaT & empty) into pandas/tests/indexes/datetimelike.py so that they get tested for all DTI, PI, and TDI

This comment has been minimized.

@jreback

jreback Apr 25, 2017

Contributor

then in the sub-classes call the super-class for testing (and add addtional); so these are all called test_map.

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

Sorry I misunderstood your comment on the last PR and thought you asked me to put these here (test_datetimelike) rather than than there. Thanks for making that clearer.

def test_map_with_categorical_series(self):
# GH 12756
a = pd.Index([1, 2, 3, 4])
b = pd.Series(["even", "odd", "even", "odd"],

This comment has been minimized.

@jreback

jreback Apr 25, 2017

Contributor

this is really odd. you are mapping the codes??

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

I wanted to see if someone did try to do this (not sure why you would) that it would work as expected. So yes it maps the codes in this case. Is there a different preferred behavior?

@jreback

This comment has been minimized.

Contributor

jreback commented May 19, 2017

pls rebase / update when you can

@nateyoder

Sorry for the long delay here. I ran into (and am still running into) some issues with IntervalIndex in which the get_indexer function appears to be buggy (#16410). I skipped that test for now but depending on the desired behavior will probably have to do a custom map function for that? Also I'm not sure I fully understand the new pytest behavior so sorry if there are issues there as well.

def test_map_with_categorical_series(self):
# GH 12756
a = pd.Index([1, 2, 3, 4])
b = pd.Series(["even", "odd", "even", "odd"],

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

I wanted to see if someone did try to do this (not sure why you would) that it would work as expected. So yes it maps the codes in this case. Is there a different preferred behavior?

@@ -521,6 +521,7 @@ Other Enhancements
- The ``display.show_dimensions`` option can now also be used to specify
whether the length of a ``Series`` should be shown in its repr (:issue:`7117`).
- ``parallel_coordinates()`` has gained a ``sort_labels`` keyword arg that sorts class labels and the colours assigned to them (:issue:`15908`)

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

Removed

@@ -8,10 +8,10 @@
from pandas.core.dtypes.missing import isnull
from pandas.core.dtypes.generic import ABCDataFrame, ABCSeries, ABCIndexClass
from pandas.core.dtypes.common import is_object_dtype, is_list_like, is_scalar
from pandas.core.dtypes.common import is_object_dtype, is_list_like, is_scalar, is_extension_type

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

👍

@@ -933,6 +933,44 @@ def _reduce(self, op, name, axis=0, skipna=True, numeric_only=None,
klass=self.__class__.__name__, op=name))
return func(**kwds)
def _map_values(self, values, arg, na_action=None):
if is_extension_type(self.dtype):

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

👍

Parameters
----------
data : {dict, DictWithoutMissing}

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

👍

result = self.index.map(lambda x: pd.NaT if x == self.index[0] else x)
expected = Index([pd.NaT] + self.index[1:].tolist())
tm.assert_index_equal(result, expected)
series_map = pd.Series(expected, self.index)

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

👍

@@ -74,3 +74,29 @@ def test_union(self):
for case in cases:
result = first.union(case)
self.assertTrue(tm.equalContents(result, everything))
def test_map(self):
expected = self.index + 1

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

👍

@@ -74,3 +74,29 @@ def test_union(self):
for case in cases:
result = first.union(case)
self.assertTrue(tm.equalContents(result, everything))

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

Sorry I misunderstood your comment on the last PR and thought you asked me to put these here (test_datetimelike) rather than than there. Thanks for making that clearer.

@@ -1398,6 +1398,17 @@ def get_value_maybe_box(self, series, key):
key, tz=self.tz)
return _maybe_box(self, values, series, key)
@Appender(_index_shared_docs['_get_values_from_dict'])
def _get_values_from_dict(self, data):

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

See the above comment.

@@ -704,6 +704,14 @@ def __rsub__(self, other):
def _add_delta(self, other):
return NotImplemented
@Appender(_index_shared_docs['_get_values_from_dict'])
def _get_values_from_dict(self, data):

This comment has been minimized.

@nateyoder

nateyoder May 21, 2017

Contributor

I would assume it does get hit indirectly as it was essentially pulled into the subclasses from the pd.Series instantiation. It is essentially replicating the behavior that was previously in lines 188-203 of pandas/core/series.py and allowing each object to handle it as seen fit rather than doing it in an if conditional. Personally this way make more sense to me but since I ended up not making use of this functionality outside of the Series instantiation I'm happy to revert the changes if you'd prefer.

@jreback

This comment has been minimized.

Contributor

jreback commented Jul 26, 2017

can you rebase / update

@jreback

This comment has been minimized.

Contributor

jreback commented Aug 18, 2017

@nateyoder can you rebase / update. sorry didn't get to review this soon.

@jreback

This comment has been minimized.

Contributor

jreback commented Oct 28, 2017

@nateyoder going to finaly get this in! can you rebase and move note to 0.22.0

@nateyoder

This comment has been minimized.

Contributor

nateyoder commented Oct 28, 2017

Hi @jreback. Sorry the problem has totally been on my side. Yes I'd love to get it in as well though I unfortunately won't be able to work on it this weekend. If I try to get you updates early next week would that work? Sorry for the delay!

@jreback

This comment has been minimized.

Contributor

jreback commented Oct 28, 2017

@nateyoder sure! that is fine. just ping when ready.

@nateyoder

This comment has been minimized.

Contributor

nateyoder commented Oct 31, 2017

Hi @jreback I tried to update this but ran into some issues locally with the tests you added from mapping type (#17491). I unfortunately don't have a ton of time to spend debugging right now so any insight you might be able to provide would be awesome.

@jreback

This comment has been minimized.

Contributor

jreback commented Nov 19, 2017

also refactored to remove turning things into object dtypes unecessarily

PR

In [1]:         np.random.seed(1234)
   ...:         map_size = 10000
   ...:         s = Series(np.random.randint(0, map_size, 100000))
   ...:         map_series = Series(map_size - np.arange(map_size))
   ...: 

In [2]: %timeit s.map(map_series)
773 µs ± 36.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

0.21.0

In [2]: %timeit s.map(map_series)
9.3 ms ± 391 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
@jreback

This comment has been minimized.

Contributor

jreback commented Nov 19, 2017

@TomAugspurger and @jorisvandenbossche if you have any comments.

@jreback jreback added this to the 0.22.0 milestone Nov 19, 2017

@jorisvandenbossche

Looks good, just a small comment

tm.assert_index_equal(self.index.map(series_map), expected)
dict_map = {i: e for e, i in zip(expected, self.index)}
tm.assert_index_equal(self.index.map(dict_map), expected)

This comment has been minimized.

@jorisvandenbossche

jorisvandenbossche Nov 19, 2017

Member

One question: in the base tests you have the case of an empty mapping generating an Index of NaNs. Should there be a test for that here as well that it gives an Index of NaTs ?

This comment has been minimized.

@jreback

jreback Nov 24, 2017

Contributor

there is no easy way to do this actually, e.g.

In [2]: pd.date_range('20130101', periods=3).map({})
Out[2]: Float64Index([nan, nan, nan], dtype='float64')

I could special case this I suppose (e.g. empty dict).

This comment has been minimized.

@jreback

jreback Nov 25, 2017

Contributor

I actually tried to fix this, but it goes down a rabbit hole. if you want to open an issue ok I guess.

# Dictionary does not have a default. Thus it's safe to
# convert to an Series for efficiency.
from pandas import Series
mapper = Series(mapper, index=mapper.keys())

This comment has been minimized.

@TomAugspurger

TomAugspurger Nov 20, 2017

Contributor

Is passing index=mapper.keys() necessary?

This comment has been minimized.

@jreback

jreback Nov 24, 2017

Contributor

nope

This comment has been minimized.

@jreback

jreback Nov 24, 2017

Contributor

actually this is to handle some odd-ball cases where you have tuples as keys in the dictionary

def map(self, mapper):
"""Apply mapper function to an index.
def map(self, mapper, na_action=None):
"""Map values of Series using input correspondence (which can be a

This comment has been minimized.

@TomAugspurger

TomAugspurger Nov 20, 2017

Contributor

The first sentence should be a single line so that it looks OK in the autosummary table.

This comment has been minimized.

@jreback

jreback Nov 24, 2017

Contributor

done

@@ -2245,14 +2230,14 @@ def unstack(self, level=-1, fill_value=None):
# ----------------------------------------------------------------------
# function application
def map(self, arg, na_action=None):
def map(self, mapper, na_action=None):

This comment has been minimized.

@TomAugspurger

TomAugspurger Nov 20, 2017

Contributor

Could you add a release note for this in API-breaking changes.

This comment has been minimized.

@jreback

jreback Nov 24, 2017

Contributor

reverted (was an error)

@jreback jreback merged commit 467ee2b into pandas-dev:master Nov 25, 2017

3 checks passed

ci/circleci Your tests passed on CircleCI!
Details
continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
@jreback

This comment has been minimized.

Contributor

jreback commented Nov 25, 2017

thanks @nateyoder glad we got this in!

@jreback jreback referenced this pull request Nov 25, 2017

Open

Index.map followups #18482

2 of 3 tasks complete
@nateyoder

This comment has been minimized.

Contributor

nateyoder commented Nov 25, 2017

@jreback thanks for doing all the work to finish it up!! Really appreciate you picking up the slack!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment