Convert DataFrame to Series with multi-level Index. Columns become the second level of the resulting hierarchical index Returns ------- stacked : Series or DataFrame
(
frame: DataFrame, level=-1, dropna: bool = True, sort: bool = True
)
| 656 | |
| 657 | |
| 658 | def stack( |
| 659 | frame: DataFrame, level=-1, dropna: bool = True, sort: bool = True |
| 660 | ) -> Series | DataFrame: |
| 661 | """ |
| 662 | Convert DataFrame to Series with multi-level Index. Columns become the |
| 663 | second level of the resulting hierarchical index |
| 664 | |
| 665 | Returns |
| 666 | ------- |
| 667 | stacked : Series or DataFrame |
| 668 | """ |
| 669 | |
| 670 | def stack_factorize(index): |
| 671 | if index.is_unique: |
| 672 | return index, np.arange(len(index)) |
| 673 | codes, categories = factorize_from_iterable(index) |
| 674 | return categories, codes |
| 675 | |
| 676 | N, K = frame.shape |
| 677 | |
| 678 | # Will also convert negative level numbers and check if out of bounds. |
| 679 | level_num = frame.columns._get_level_number(level) |
| 680 | |
| 681 | if isinstance(frame.columns, MultiIndex): |
| 682 | return _stack_multi_columns( |
| 683 | frame, level_num=level_num, dropna=dropna, sort=sort |
| 684 | ) |
| 685 | elif isinstance(frame.index, MultiIndex): |
| 686 | new_levels = list(frame.index.levels) |
| 687 | new_codes = [lab.repeat(K) for lab in frame.index.codes] |
| 688 | |
| 689 | clev, clab = stack_factorize(frame.columns) |
| 690 | new_levels.append(clev) |
| 691 | new_codes.append(np.tile(clab, N).ravel()) |
| 692 | |
| 693 | new_names = list(frame.index.names) |
| 694 | new_names.append(frame.columns.name) |
| 695 | new_index = MultiIndex( |
| 696 | levels=new_levels, codes=new_codes, names=new_names, verify_integrity=False |
| 697 | ) |
| 698 | else: |
| 699 | levels, (ilab, clab) = zip( |
| 700 | *map(stack_factorize, (frame.index, frame.columns)), strict=True |
| 701 | ) |
| 702 | codes = ilab.repeat(K), np.tile(clab, N).ravel() |
| 703 | new_index = MultiIndex( |
| 704 | levels=levels, |
| 705 | codes=codes, |
| 706 | names=[frame.index.name, frame.columns.name], |
| 707 | verify_integrity=False, |
| 708 | ) |
| 709 | |
| 710 | new_values: ArrayLike |
| 711 | if not frame.empty and frame._is_homogeneous_type: |
| 712 | # For homogeneous EAs, frame._values will coerce to object. So |
| 713 | # we concatenate instead. |
| 714 | dtypes = list(frame.dtypes._values) |
| 715 | dtype = dtypes[0] |
no test coverage detected