Эта игрушка воспроизводит проблему:
import pandas as pd
print(f"pandas: {pd.__version__}")
!python --version
#artificial 2
qf = pd.Series(index = pd.to_datetime(['12Dec2020', '13Dec2020','14Dec2020', '15Dec2020','16Dec2020']),
data= [1,1,-1,-1,-1],
name=('coz1', 'this_bar'),
)
qf.index.name="Date"
qf = qf.groupby(
(qf != qf.shift())
.cumsum()
).cumsum().apply(int)
qf.head(10)
Когда я запускаю его в 0.25.3 Pandas
, он работает.
pandas: 0.25.3
Python 3.7.11
Date
2020-12-12 1
2020-12-13 2
2020-12-14 -1
2020-12-15 -2
2020-12-16 -3
Name: (coz1, this_bar), dtype: int64
Но когда я запускаю его в 1.2.4 Pandas
, он завершается с ошибкой InvalidIndexError
pandas: 1.2.4
Python 3.9.4
---------------------------------------------------------------------------
InvalidIndexError Traceback (most recent call last)
<ipython-input-1-f28184e3b2db> in <module>
9 )
10 qf.index.name="Date"
---> 11 qf = qf.groupby(
12 (qf != qf.shift())
13 .cumsum()
~\.conda\envs\yagi\lib\site-packages\pandas\core\series.py in groupby(self, by, axis, level, as_index, sort, group_keys, squeeze, observed, dropna)
1718 axis = self._get_axis_number(axis)
1719
-> 1720 return SeriesGroupBy(
1721 obj=self,
1722 keys=by,
~\.conda\envs\yagi\lib\site-packages\pandas\core\groupby\groupby.py in __init__(self, obj, keys, axis, level, grouper, exclusions, selection, as_index, sort, group_keys, squeeze, observed, mutated, dropna)
558 from pandas.core.groupby.grouper import get_grouper
559
--> 560 grouper, exclusions, obj = get_grouper(
561 obj,
562 keys,
~\.conda\envs\yagi\lib\site-packages\pandas\core\groupby\grouper.py in get_grouper(obj, key, axis, level, sort, observed, mutated, validate, dropna)
796 for i, (gpr, level) in enumerate(zip(keys, levels)):
797
--> 798 if is_in_obj(gpr): # df.groupby(df['name'])
799 in_axis, name = True, gpr.name
800 exclusions.add(name)
~\.conda\envs\yagi\lib\site-packages\pandas\core\groupby\grouper.py in is_in_obj(gpr)
788 return False
789 try:
--> 790 return gpr is obj[gpr.name]
791 except (KeyError, IndexError):
792 # IndexError reached in e.g. test_skip_group_keys when we pass
~\.conda\envs\yagi\lib\site-packages\pandas\core\series.py in __getitem__(self, key)
857 try:
858 # For labels that don't resolve as scalars like tuples and frozensets
--> 859 result = self._get_value(key)
860
861 return result
~\.conda\envs\yagi\lib\site-packages\pandas\core\series.py in _get_value(self, label, takeable)
959
960 # Similar to Index.get_value, but we do not fall back to positional
--> 961 loc = self.index.get_loc(label)
962 return self.index._get_values_for_loc(self, loc, label)
963
~\.conda\envs\yagi\lib\site-packages\pandas\core\indexes\datetimes.py in get_loc(self, key, method, tolerance)
644 """
645 if not is_scalar(key):
--> 646 raise InvalidIndexError(key)
647
648 orig_key = key
InvalidIndexError: ('coz1', 'this_bar')
Я определил причину как передачу кортежа параметру name
вызова Series
. Если я сделаю это простой строкой, все будет работать нормально.
import pandas as pd
print(f"pandas: {pd.__version__}")
!python --version
qf=None
#artificial 2
jf = pd.Series(index = pd.to_datetime(['12Dec2020', '13Dec2020','14Dec2020', '15Dec2020','16Dec2020']),
data= [1,1,-1,-1,-1],
name="NotATuple",
)
jf.index.name="Date"
jf = jf.groupby(
(jf != jf.shift())
.cumsum()
).cumsum().apply(int)
jf.head(10)
pandas: 1.2.4
Python 3.9.4
Date
2020-12-12 1
2020-12-13 2
2020-12-14 -1
2020-12-15 -2
2020-12-16 -3
Name: NotATuple, dtype: int64
это большая проблема, потому что серия qf
создается фрагментом .loc
многоуровневого столбца DataFrame, а значение позже добавляется обратно в исходный фрейм данных, из которого оно было получено. Так что я вынужден сделать грубый хак, показанный во фрагменте:
wf = df.loc[:,idx[sec, 'this_bar']].dropna(axis="index")
#hack pt1 of 2
original_name = wf.name
wf.name="placeholder"
wf = wf.groupby(
(wf != wf.shift())
.cumsum()
).cumsum().apply(int)
pf = wf.shift()
#hack pt2 of 2
wf.name=original_name
pf.name=original_name
df.loc[:,idx[sec, 'this_bar']] == np.nan #reset
df.loc[:,idx[sec, 'this_bar']] = wf
df.loc[:,idx[sec, 'prev_bar']] = pf
#cosmetic column:
df.loc[:,idx[sec, f'prev_{period}']] = df.loc[:,idx[sec, 'prev_bar']]
Интересно, это ошибка в Pandas 1.2.4?