1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
U
¬ý°dX‘ã    @s€dZddlmZddlmZmZmZmZddlZddl    Z
ddl m Z ddl mZmZmZmZddlmZddlmZdd    lmZdd
lmZmZmZdd lmZdd lmZm Z ddl!m"m#Z$dd l%m&Z&ddl'm(Z(ddl)m*Z*ddl+m,Z,m-Z-m.Z.ddl/m0Z0ddl1m2Z2er$ddl3m4Z4Gdd„dƒZ5eGdd„dƒƒZ6d(ddddddddœdd „Z7dd!œd"d#„Z8d$d%œd&d'„Z9dS))z]
Provide user facing operators for doing the split part of the
split-apply-combine paradigm.
é)Ú annotations)Ú TYPE_CHECKINGÚHashableÚIteratorÚfinalN)Úusing_copy_on_write)Ú    ArrayLikeÚAxisÚNDFrameTÚnpt)ÚInvalidIndexError)Úcache_readonly)Úfind_stack_level)Úis_categorical_dtypeÚ is_list_likeÚ    is_scalar)Ú
algorithms)Ú CategoricalÚExtensionArray)Ú    DataFrame)Úops)Úrecode_for_groupby)ÚCategoricalIndexÚIndexÚ
MultiIndex)ÚSeries)Ú pprint_thing)ÚNDFramecsþeZdZUdZded<ded<ded<ded<dZd    ed
<‡fd d „Zd/dddddœdd„Zd0ddddœdd„Ze    d1d dœddddœdd„ƒZ
e    e d d!œd"d#„ƒƒZ e    e d$d%„ƒƒZ e    e d&d'„ƒƒZe    e d(d)„ƒƒZe    e d*d+„ƒƒZe    d,d!œd-d.„ƒZ‡ZS)2ÚGroupera˜
    A Grouper allows the user to specify a groupby instruction for an object.
 
    This specification will select a column via the key parameter, or if the
    level and/or axis parameters are given, a level of the index of the target
    object.
 
    If `axis` and/or `level` are passed as keywords to both `Grouper` and
    `groupby`, the values passed to `Grouper` take precedence.
 
    Parameters
    ----------
    key : str, defaults to None
        Groupby key, which selects the grouping column of the target.
    level : name/number, defaults to None
        The level for the target index.
    freq : str / frequency object, defaults to None
        This will groupby the specified frequency if the target selection
        (via key or level) is a datetime-like object. For full specification
        of available frequencies, please see `here
        <https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#offset-aliases>`_.
    axis : str, int, defaults to 0
        Number/name of the axis.
    sort : bool, default to False
        Whether to sort the resulting labels.
    closed : {'left' or 'right'}
        Closed end of interval. Only when `freq` parameter is passed.
    label : {'left' or 'right'}
        Interval boundary to use for labeling.
        Only when `freq` parameter is passed.
    convention : {'start', 'end', 'e', 's'}
        If grouper is PeriodIndex and `freq` parameter is passed.
 
    origin : Timestamp or str, default 'start_day'
        The timestamp on which to adjust the grouping. The timezone of origin must
        match the timezone of the index.
        If string, must be one of the following:
 
        - 'epoch': `origin` is 1970-01-01
        - 'start': `origin` is the first value of the timeseries
        - 'start_day': `origin` is the first day at midnight of the timeseries
 
        .. versionadded:: 1.1.0
 
        - 'end': `origin` is the last value of the timeseries
        - 'end_day': `origin` is the ceiling midnight of the last day
 
        .. versionadded:: 1.3.0
 
    offset : Timedelta or str, default is None
        An offset timedelta added to the origin.
 
        .. versionadded:: 1.1.0
 
    dropna : bool, default True
        If True, and if group keys contain NA values, NA values together with
        row/column will be dropped. If False, NA values will also be treated as
        the key in groups.
 
        .. versionadded:: 1.2.0
 
    Returns
    -------
    A specification for a groupby instruction
 
    Examples
    --------
    Syntactic sugar for ``df.groupby('A')``
 
    >>> df = pd.DataFrame(
    ...     {
    ...         "Animal": ["Falcon", "Parrot", "Falcon", "Falcon", "Parrot"],
    ...         "Speed": [100, 5, 200, 300, 15],
    ...     }
    ... )
    >>> df
       Animal  Speed
    0  Falcon    100
    1  Parrot      5
    2  Falcon    200
    3  Falcon    300
    4  Parrot     15
    >>> df.groupby(pd.Grouper(key="Animal")).mean()
            Speed
    Animal
    Falcon  200.0
    Parrot   10.0
 
    Specify a resample operation on the column 'Publish date'
 
    >>> df = pd.DataFrame(
    ...    {
    ...        "Publish date": [
    ...             pd.Timestamp("2000-01-02"),
    ...             pd.Timestamp("2000-01-02"),
    ...             pd.Timestamp("2000-01-09"),
    ...             pd.Timestamp("2000-01-16")
    ...         ],
    ...         "ID": [0, 1, 2, 3],
    ...         "Price": [10, 20, 30, 40]
    ...     }
    ... )
    >>> df
      Publish date  ID  Price
    0   2000-01-02   0     10
    1   2000-01-02   1     20
    2   2000-01-09   2     30
    3   2000-01-16   3     40
    >>> df.groupby(pd.Grouper(key="Publish date", freq="1W")).mean()
                   ID  Price
    Publish date
    2000-01-02    0.5   15.0
    2000-01-09    2.0   30.0
    2000-01-16    3.0   40.0
 
    If you want to adjust the start of the bins based on a fixed timestamp:
 
    >>> start, end = '2000-10-01 23:30:00', '2000-10-02 00:30:00'
    >>> rng = pd.date_range(start, end, freq='7min')
    >>> ts = pd.Series(np.arange(len(rng)) * 3, index=rng)
    >>> ts
    2000-10-01 23:30:00     0
    2000-10-01 23:37:00     3
    2000-10-01 23:44:00     6
    2000-10-01 23:51:00     9
    2000-10-01 23:58:00    12
    2000-10-02 00:05:00    15
    2000-10-02 00:12:00    18
    2000-10-02 00:19:00    21
    2000-10-02 00:26:00    24
    Freq: 7T, dtype: int64
 
    >>> ts.groupby(pd.Grouper(freq='17min')).sum()
    2000-10-01 23:14:00     0
    2000-10-01 23:31:00     9
    2000-10-01 23:48:00    21
    2000-10-02 00:05:00    54
    2000-10-02 00:22:00    24
    Freq: 17T, dtype: int64
 
    >>> ts.groupby(pd.Grouper(freq='17min', origin='epoch')).sum()
    2000-10-01 23:18:00     0
    2000-10-01 23:35:00    18
    2000-10-01 23:52:00    27
    2000-10-02 00:09:00    39
    2000-10-02 00:26:00    24
    Freq: 17T, dtype: int64
 
    >>> ts.groupby(pd.Grouper(freq='17min', origin='2000-01-01')).sum()
    2000-10-01 23:24:00     3
    2000-10-01 23:41:00    15
    2000-10-01 23:58:00    45
    2000-10-02 00:15:00    45
    Freq: 17T, dtype: int64
 
    If you want to adjust the start of the bins with an `offset` Timedelta, the two
    following lines are equivalent:
 
    >>> ts.groupby(pd.Grouper(freq='17min', origin='start')).sum()
    2000-10-01 23:30:00     9
    2000-10-01 23:47:00    21
    2000-10-02 00:04:00    54
    2000-10-02 00:21:00    24
    Freq: 17T, dtype: int64
 
    >>> ts.groupby(pd.Grouper(freq='17min', offset='23h30min')).sum()
    2000-10-01 23:30:00     9
    2000-10-01 23:47:00    21
    2000-10-02 00:04:00    54
    2000-10-02 00:21:00    24
    Freq: 17T, dtype: int64
 
    To replace the use of the deprecated `base` argument, you can now use `offset`,
    in this example it is equivalent to have `base=2`:
 
    >>> ts.groupby(pd.Grouper(freq='17min', offset='2min')).sum()
    2000-10-01 23:16:00     0
    2000-10-01 23:33:00     9
    2000-10-01 23:50:00    36
    2000-10-02 00:07:00    39
    2000-10-02 00:24:00    24
    Freq: 17T, dtype: int64
    ÚboolÚsortÚdropnaú Index | NoneÚ
_gpr_indexÚ_grouper)ÚkeyÚlevelÚfreqÚaxisr r!ztuple[str, ...]Ú _attributescs*| d¡dk    rddlm}|}tƒ |¡S)Nr'r)Ú TimeGrouper)ÚgetZpandas.core.resampler*ÚsuperÚ__new__)ÚclsÚargsÚkwargsr*©Ú    __class__©úRd:\z\workplace\vscode\pyvenv\venv\Lib\site-packages\pandas/core/groupby/grouper.pyr-ùs zGrouper.__new__NrFTr    ÚNone)r(r r!ÚreturncCsR||_||_||_||_||_||_d|_d|_d|_d|_    d|_
d|_ d|_ dS©N) r%r&r'r(r r!Ú_grouper_deprecatedÚ_indexer_deprecatedÚ_obj_deprecatedr#Zbinnerr$Ú_indexer)Úselfr%r&r'r(r r!r3r3r4Ú__init__s    zGrouper.__init__r
z tuple[ops.BaseGrouper, NDFrameT])ÚobjÚvalidater6c    CsF| |¡\}}}t||jg|j|j|j||jd\}}}||_||fS)zô
        Parameters
        ----------
        obj : Series or DataFrame
        validate : bool, default True
            if True, validate the grouper
 
        Returns
        -------
        a tuple of grouper, obj (possibly sorted)
        )r(r&r r?r!)Ú _set_grouperÚ get_grouperr%r(r&r r!r8)r<r>r?Ú_Úgrouperr3r3r4Ú _get_groupersù zGrouper._get_grouper)Ú    gpr_indexr)r>r rEc
Cs°|dk    s t‚d}|jdk    r,|jdk    r,tdƒ‚|jdkrD||_|j|_|jdk    ræ|j}t|ddƒ|krºt|t    ƒrº|jdk    s|t‚|jdk    rª|j 
¡}|j  |¡}|  |j ¡}qä|j  |j ¡}n*||j krÔtd|›dƒ‚t|||d}nn| |j¡}|jdk    rT|j}    t|tƒr4| |    ¡}    t| |    ¡|j|    d}n |    d|jfkrTtd|    ›d    ƒ‚|jsb|rš|jsš|jj
d
d d }|_|  |¡}|j ||jd }||_||_|||fS)a·
        given an object and the specifications, setup the internal grouper
        for this particular specification
 
        Parameters
        ----------
        obj : Series or DataFrame
        sort : bool, default False
            whether the resulting grouper should be sorted
        gpr_index : Index or None, default None
 
        Returns
        -------
        NDFrame
        Index
        np.ndarray[np.intp] | None
        Nz2The Grouper cannot specify both a key and a level!ÚnamezThe grouper name z  is not found©rFrz
The level z  is not validZ    mergesortÚfirst)ÚkindZ na_position©r()ÚAssertionErrorr%r&Ú
ValueErrorr$r9r;ÚgetattrÚ
isinstancerZargsortZtakeÚindexZ
_info_axisÚKeyErrorrÚ    _get_axisr(rZ_get_level_numberZ_get_level_valuesÚnamesrFr Zis_monotonic_increasingÚarrayr:r#)
r<r>r rEÚindexerr%Zreverse_indexerZ unsorted_axÚaxr&r3r3r4r@7sJ 
 
 
 
 
 
ÿ 
zGrouper._set_grouperr©r6cCs8tjt|ƒj›dttƒd|j}|dkr4tdƒ‚|S)NzS.ax is deprecated and will be removed in a future version. Use Resampler.ax instead©Ú
stacklevelz1_set_grouper must be called before ax is accessed)ÚwarningsÚwarnÚtypeÚ__name__Ú FutureWarningrr#rL)r<rOr3r3r4rUsüz
Grouper.axcCs$tjt|ƒj›dttƒd|jS)Nz^.indexer is deprecated and will be removed in a future version. Use Resampler.indexer instead.rW)rYrZr[r\r]rr9©r<r3r3r4rT›s üzGrouper.indexercCs$tjt|ƒj›dttƒd|jS)NzX.obj is deprecated and will be removed in a future version. Use GroupBy.indexer instead.rW)rYrZr[r\r]rr:r^r3r3r4r>¦s üz Grouper.objcCs$tjt|ƒj›dttƒd|jS)Nz\.grouper is deprecated and will be removed in a future version. Use GroupBy.grouper instead.rW)rYrZr[r\r]rr8r^r3r3r4rC±s üzGrouper.groupercCs&tjt|ƒj›dttƒd|jjS)NzZ.groups is deprecated and will be removed in a future version. Use GroupBy.groups instead.rW)rYrZr[r\r]rr8Úgroupsr^r3r3r4r_¼s üzGrouper.groupsÚstrcs8‡fdd„ˆjDƒ}d |¡}tˆƒj}|›d|›dS)Nc3s4|],}tˆ|ƒdk    r|›dttˆ|ƒƒ›VqdS)Nú=)rMÚrepr)Ú.0Ú    attr_namer^r3r4Ú    <genexpr>Êsþz#Grouper.__repr__.<locals>.<genexpr>z, ú(ú))r)Újoinr[r\)r<Z
attrs_listÚattrsZcls_namer3r^r4Ú__repr__Ès 
þ
 
zGrouper.__repr__)NNNrFT)T)F)r\Ú
__module__Ú __qualname__Ú__doc__Ú__annotations__r)r-r=rDrr@ÚpropertyrUrTr>rCr_rjÚ __classcell__r3r3r1r4r9sN
9      ùÿÿÿU                
rc
@sBeZdZUdZdZded<dZded<ded<ded    <d
ed <d:d
ddddddddœdd„Zddœdd„Zddœdd„Z    e
ddœdd„ƒZ e
ddœdd „ƒZ e
d!dœd"d#„ƒZ ed$dœd%d&„ƒZe
d'dœd(d)„ƒZed*dœd+d,„ƒZe
d-dœd.d/„ƒZe
d
dœd0d1„ƒZe
d
dœd2d3„ƒZe
d4dœd5d6„ƒZe
d7dœd8d9„ƒZdS);ÚGroupingah
    Holds the grouping information for a single key
 
    Parameters
    ----------
    index : Index
    grouper :
    obj : DataFrame or Series
    name : Label
    level :
    observed : bool, default False
        If we are a Categorical, use the observed values
    in_axis : if the Grouping is a column in self.obj and hence among
        Groupby.exclusions list
    dropna : bool, default True
        Whether to drop NA groups.
    uniques : Array-like, optional
        When specified, will be used for unique values. Enables including empty groups
        in the result for a BinGrouper. Must not contain duplicates.
 
    Attributes
    -------
    indices : dict
        Mapping of {group -> index_list}
    codes : ndarray
        Group codes
    group_index : Index or None
        unique groups
    groups : dict
        Mapping of {group -> label_list}
    Nz$npt.NDArray[np.signedinteger] | NoneÚ_codesr"Ú _group_indexzCategorical | NoneÚ _all_grouperÚ
_orig_catsrÚ_indexTFzNDFrame | NonerzArrayLike | Noner5)rOr>r ÚobservedÚin_axisr!Úuniquesr6c
CsÒ||_||_t||ƒ}
d|_d|_||_||_||_||_||_    ||_
|    |_ |j } | dk    r’t |tƒrp| | ¡} n|} |
dkr‚| }
n|
} |  | ¡}
nèt |
tƒrô|jdk    sªt‚|
j|jdd\}}||_t |tjƒrÖ|}
n|jdj}t||jjd}
n†t |
ttttjfƒszt|
ddƒdkr8t t!|
ƒƒ}t"d|›dƒ‚| |
¡}
t#|
d    ƒr`t$|
ƒt$|ƒkszt%|
ƒ}d
|›}t|ƒ‚t |
tjƒr¤|
j&j'd krÈt|
ƒ (¡}
n$t)|
ƒrÈ|
j*|_t+|
||ƒ\}
|_|
|_dS) NF©r?rrGÚndiméú Grouper for 'ú' not 1-dimensionalÚ__len__z9Grouper result violates len(labels) == len(data)
result: )ÚmÚM),r&Ú _orig_grouperÚ_convert_grouperrtrurvÚ_sortr>Ú    _observedrxÚ_dropnaÚ_uniquesÚ_ilevelrNrÚget_level_valuesÚmaprrKrDrZ
BinGrouperÚ    groupingsÚgrouping_vectorrÚ result_indexrFrrÚnpÚndarrayrMr`r[rLÚhasattrÚlenrÚdtyperIZto_numpyrÚ
categoriesr)r<rOrCr>r&r rwrxr!ryrŒÚilevelZ index_levelZmapperZ
newgrouperZnewobjZngÚtZgrperÚerrmsgr3r3r4r=üsp 
 
 
   ÿ 
ÿþÿ
ÿ
zGrouping.__init__r`rVcCsd|j›dS)Nz    Grouping(rgrGr^r3r3r4rjeszGrouping.__repr__rcCs
t|jƒSr7)ÚiterÚindicesr^r3r3r4Ú__iter__hszGrouping.__iter__cCs
t|jƒSr7)rrŒr^r3r3r4Ú_passed_categoricalkszGrouping._passed_categoricalrcCsb|j}|dk    r|jj|St|jttfƒr2|jjSt|jt    j
ƒrJ|jj jSt|jtƒr^|jjSdSr7) rˆrvrRrNr‚rrrFrŒrÚ BaseGrouperr)r<r”r3r3r4rFos 
 z Grouping.namez
int | NonecCsL|j}|dkrdSt|tƒsH|j}||jkr<td|›dƒ‚|j |¡S|S)zS
        If necessary, converted index level name to index level position.
        NzLevel z  not in index)r&rNÚintrvrRrKrO)r<r&rOr3r3r4rˆs
 
 zGrouping._ilevelrœcCs
t|jƒSr7)r‘Ú group_indexr^r3r3r4ÚngroupsszGrouping.ngroupsz$dict[Hashable, npt.NDArray[np.intp]]cCs(t|jtjƒr|jjSt|jƒ}| ¡Sr7)rNrŒrr›r˜rZ_reverse_indexer)r<Úvaluesr3r3r4r˜”s
zGrouping.indicesznpt.NDArray[np.signedinteger]cCs
|jdS)Nr)Ú_codes_and_uniquesr^r3r3r4ÚcodesszGrouping.codesrcCs*|jdk    r|jjS|jr |jjS|jdS)zv
        Analogous to result_index, but holding an ArrayLike to ensure
        we can retain ExtensionDtypes.
        Nr|)rtrÚ_valuesršrr r^r3r3r4Úgroup_arraylike¡s
 
zGrouping.group_arraylikecCs4|jdk    r.|j}t|tƒst‚|j}| |¡S|jSr7)rtrrNrrKruZset_categories)r<Z    group_idxZcatsr3r3r4r°s 
 
zGrouping.result_indexcCsÂ|j\}}|js²|jr²t|tƒs$t‚|jrV|t|ƒk ¡rVt     t
  |j dg¡|j ¡}n\t|ƒdkr²|j}|j dk ¡}|j |dkr²t |j d|…¡}t     t
 |j |d¡|j ¡}tj||jdS)NéÿÿÿÿrrG)r r†ršrNrrKr„r‘ÚanyÚ
from_codesrŽÚappendr¡r“rŒÚargmaxrÚ nunique_intsÚinsertrZ _with_inferrF)r<r¡ryÚcatÚna_idxZ na_unique_idxr3r3r4r¼s$
 ÿ ÿzGrouping.group_indexz/tuple[npt.NDArray[np.signedinteger], ArrayLike]c    Csf|jrö|j}|j}|jrBt |j¡}||dk}|jrPt     |¡}nt 
t |ƒ¡}t j |||jd}|j}|jsÜ|dk}t |¡rÜ|jržt |ƒ}t |||¡}n>| ¡}t |d|…¡}t ||k|d|¡}t |||¡}|jsî| |j¡}||fSt|jtjƒr|jj}|jjj}nD|jdk    rDt |j|jd}|j}|j}ntj|j|j|jd\}}||fS)Nr¤)r¡r“Úorderedrr|)r“)r Zuse_na_sentinel)ršrŒr“r…rZunique1dr¡r„rŽr Zaranger‘rr¦r­r†r¥Úwherer¨r©Zreorder_categoriesrurNrr›Z
codes_inforr¢r‡Z    factorize)    r<r«r“Zucodesryr¡Zna_maskZna_coder¬r3r3r4r ÒsR   ÿ
   ÿ
zGrouping._codes_and_uniqueszdict[Hashable, np.ndarray]cCs|j t |j|j¡¡Sr7)rvÚgroupbyrr¦r¡rr^r3r3r4r_szGrouping.groups)NNNTFFTN)r\rkrlrmrrrnrsr=rjr™r ršrFrˆroržr˜r¡r£rrr r_r3r3r3r4rqÔsN
   öi >rqTFr
r    rz5tuple[ops.BaseGrouper, frozenset[Hashable], NDFrameT])r>r(r rwr?r!r6c s:ˆ |¡}|dk    rêt|tƒrXt|ƒr8t|ƒdkr8|d}|dkrêt|ƒrê| |¡}d}n’t|ƒr”t|ƒ}    |    dkrz|d}n|    dkrŒtdƒ‚ntdƒ‚t|tƒrʈ |¡j    |krâtd|›dˆ 
|¡›ƒ‚n|dksÚ|dkrâtd    ƒ‚d}|}t|t ƒr4|j ˆd
d \}
‰|j dkr |
tƒˆfS|
t|j hƒˆfSnt|tjƒrN|tƒˆfSt|tƒsf|g} d
} n|} t| ƒt|ƒk} td d „| Dƒƒ} tdd „| Dƒƒ}tdd „| Dƒƒ}| s.|s.|s.| r.|dkr.tˆtƒröt‡fdd „| Dƒƒ}n&tˆtƒst‚t‡fdd „| Dƒƒ}|s.t | ¡g} t|ttfƒr\|dkrVdgt|ƒ} |}n|gt| ƒ}g}tƒ}ddœ‡fdd„ }ddœ‡fdd„ }t| |ƒD]"\}}||ƒrÈd}| |j    ¡nÊ||ƒrdˆjdkr8|ˆkr8|rüˆj||dd|ˆ|}}}|jdkr,td|›dƒ‚| |¡n*ˆj||drZd
|d}}}nt |ƒ‚n.t|t ƒrŽ|j dk    rŽ| |j ¡d}nd
}t|t!ƒs¶t!||ˆ|||||dn|}| "|¡q¢t|ƒdkrètˆƒrètdƒ‚t|ƒdkr| "t!t#gddt$j%gt$j&dƒ¡tj||||d}
|
t|ƒˆfS) aã
    Create and return a BaseGrouper, which is an internal
    mapping of how to create the grouper indexers.
    This may be composed of multiple Grouping objects, indicating
    multiple groupers
 
    Groupers are ultimately index mappings. They can originate as:
    index mappings, keys to columns, functions, or Groupers
 
    Groupers enable local references to axis,level,sort, while
    the passed in axis, level, and sort are 'global'.
 
    This routine tries to figure out what the passing in references
    are and then creates a Grouping for each one, combined into
    a BaseGrouper.
 
    If observed & we have a categorical grouper, only show the observed
    values.
 
    If validate, then check for key/level overlaps.
 
    Nr|rzNo group keys passed!z*multiple levels only valid with MultiIndexz level name z is not the name of the r¤z2level > 0 or level < -1 only valid with MultiIndexFrzcss |]}t|ƒpt|tƒVqdSr7)ÚcallablerNÚdict©rcÚgr3r3r4re{szget_grouper.<locals>.<genexpr>css|]}t|ttfƒVqdSr7)rNrrqr²r3r3r4re|scss$|]}t|tttttjfƒVqdSr7)rNÚlistÚtuplerrrŽrr²r3r3r4re}sc3s$|]}|ˆjkp|ˆjjkVqdSr7)ÚcolumnsrOrRr²©r>r3r4reŠsc3s|]}|ˆjjkVqdSr7)rOrRr²r·r3r4resrrVc
sPt|ƒsLˆjdkrdSˆjd}z| |¡Wntttfk
rJYdSXdS)Nr|Fr¤T)Ú_is_label_liker{ZaxesZget_locrPÚ    TypeErrorr )r%Úitemsr·r3r4Ú
is_in_axisŸs
 
zget_grouper.<locals>.is_in_axisc
sšt|dƒsdStƒrhzˆ|j}Wntttfk
r>YdSXt|tƒrdt|tƒrd|j     |jd¡SdSz|ˆ|jkWStttfk
r”YdSXdS)NrFFr)
rrrFrPÚ
IndexErrorr rNrZ_mgrZreferences_same_values)ÚgprZobj_gpr_columnr·r3r4Ú    is_in_obj¯s"
ÿzget_grouper.<locals>.is_in_objTrJr}r~)r>r&r rwrxr!rœ)r’)r r!)'rQrNrrr‘rr‰rLr`rFZ_get_axis_namerrDr%Ú    frozensetrr›r´r¥rÚallrrKÚcomÚasarray_tuplesaferµÚsetÚzipÚaddr{Z_check_label_or_level_ambiguityZ_is_level_referencerPrqr§rrŽrSZintp)r>r%r(r&r rwr?r!Z
group_axisZnlevelsrCÚkeysZmatch_axis_lengthZ any_callableZ any_groupersZ any_arraylikeZall_in_columns_indexÚlevelsr‹Z
exclusionsr»r¾r½rxrFZpingr3r·r4rAsÖ 
    
 
 
 
 
ÿ     ÿÿþýüû  ÿ
 
 
 
 
 öø ô$rArVcCst|ttfƒp|dk    ot|ƒSr7)rNr`rµr)Úvalr3r3r4r¸þsr¸rrJcCsœt|tƒr|jSt|tƒr:|j |¡r,|jS| |¡jSn^t|tƒrJ|jSt|t    t
t t t jfƒr”t|ƒt|ƒkrxtdƒ‚t|t    t
fƒrt |¡}|S|SdS)Nz$Grouper and axis must be same length)rNr±r+rrOÚequalsr¢Zreindexrr´rµrrrŽrr‘rLrÁrÂ)r(rCr3r3r4rƒs
 
 
 
rƒ)NrNTFTT):rmÚ
__future__rÚtypingrrrrrYÚnumpyrŽZpandas._configrZpandas._typingrr    r
r Z pandas.errorsr Zpandas.util._decoratorsr Zpandas.util._exceptionsrZpandas.core.dtypes.commonrrrZ pandas.corerZpandas.core.arraysrrZpandas.core.commonÚcoreÚcommonrÁZpandas.core.framerZpandas.core.groupbyrZpandas.core.groupby.categoricalrZpandas.core.indexes.apirrrZpandas.core.seriesrZpandas.io.formats.printingrZpandas.core.genericrrrqrAr¸rƒr3r3r3r4Ú<module>sP            Eøi