ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Python/Pandas/GroupBy
    코딩/Python 2024. 7. 13. 00:22
    728x90

    https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html# 번역본

    Group by: split-apply-combine / 그룹화: 분할-적용-결합

    By “group by” we are referring to a process involving one or more of the following steps:

    • Splitting the data into groups based on some criteria.
    • Applying a function to each group independently.
    • Combining the results into a data structure.

    "그룹화"는 다음 단계 중 하나 이상을 포함하는 프로세스를 의미한다.

    • 일부 기준에 따라 데이터를 그룹으로 분할.
    • 각 그룹에 독립적으로 기능을 적용.
    • 결과를 데이터 구조로 결합.

    Out of these, the split step is the most straightforward. In the apply step, we might wish to do one of the following:

    이 중에서 분할 단계가 가장 간단하다. 적용 단계에서 다음 중 하나를 수행할 수 있다.

     

    • Aggregation: compute a summary statistic (or statistics) for each group. Some examples:
      • Compute group sums or means
      • Compute group sizes / counts
    • Transformation: perform some group-specific computations and return a like-indexed object. Some examples:
      • Standardize data (zscore) within a group
      • Filling NAs within groups with a value derived from each group
    • Filtration: discard some groups, according to a group-wise computation that evaluates to True or False. Some examples:
      • Discard data that belong to groups with only a few members
      • Filter out data based on the group sum or mean
    • 집계: 각 그룹에 대한 요약 통계(또는 통계)를 계산한다. 몇 가지 예:
      • 그룹 합계 또는 평균을 계산
      • 그룹 크기/개수를 계산
    • 변환: 일부 그룹별 계산을 수행하고 색인이 유사한 개체를 반환한다. 몇 가지 예:
      • 그룹 내 데이터(zscore)를 표준화
      • 각 그룹에서 파생된 값으로 그룹 내의 NA를 채운다.
    • 필터링: True 또는 False로 평가되는 그룹별 계산에 따라 일부 그룹을 삭제한다. 몇 가지 예:
      • 소수의 구성원만 있는 그룹에 속한 데이터를 폐기
      • 그룹 합계 또는 평균을 기준으로 데이터를 필터링

    Many of these operations are defined on GroupBy objects. These operations are similar to those of the aggregating API, window API, and resample API.

    It is possible that a given operation does not fall into one of these categories or is some combination of them. In such a case, it may be possible to compute the operation using GroupBy’s apply method. This method will examine the results of the apply step and try to sensibly combine them into a single result if it doesn’t fit into either of the above three categories.

    이러한 작업 중 대부분은 GroupBy 개체에 정의되어 있다. 이러한 작업은 집계 API, 윈도우 API 및 리샘플 API의 작업과 유사하다.

    특정 작업이 이러한 범주 중 하나에 속하지 않거나 이러한 범주가 조합된 것일 수도 있다. 이러한 경우 GroupBy의 적용 메서드를 사용하여 작업을 계산하는 것이 가능할 수 있다. 이 방법은 적용 단계의 결과를 검사하고 위의 세 가지 범주 중 하나에 맞지 않는 경우 이를 단일 결과로 현명하게 결합하려고 시도한다.

    Note

    An operation that is split into multiple steps using built-in GroupBy operations will be more efficient than using the apply method with a user-defined Python function.

    내장된 GroupBy 작업을 사용하여 여러 단계로 분할되는 작업은 사용자 정의 Python 함수와 함께 적용 메서드를 사용하는 것보다 더 효율적이다.

    The name GroupBy should be quite familiar to those who have used a SQL-based tool (or itertools), in which you can write code like:

    GroupBy라는 이름은 다음과 같은 코드를 작성할 수 있는 SQL 기반 도구(또는 itertools)를 사용한 사람들에게 매우 익숙할 것이다.

    SELECT Column1, Column2, mean(Column3), sum(Column4)
    FROM SomeTable
    GROUP BY Column1, Column2

    We aim to make operations like this natural and easy to express using pandas. We’ll address each area of GroupBy functionality, then provide some non-trivial examples / use cases.

    See the cookbook for some advanced strategies.

    우리는 pandas를 사용하여 이러한 작업을 자연스럽고 쉽게 표현하는 것을 목표로 한다. GroupBy 기능의 각 영역을 살펴본 다음 몇 가지 중요한 예/사용 사례를 제공한다.

    몇 가지 고급 전략은 cookbook을 참조하라.

    Splitting an object into groups / 개체를 그룹으로 나누기

    The abstract definition of grouping is to provide a mapping of labels to group names. To create a GroupBy object (more on what the GroupBy object is later), you may do the following:

    그룹화의 추상적 정의는 레이블을 그룹 이름에 매핑하는 것이다. GroupBy 개체를 생성하려면(GroupBy 개체가 무엇인지 나중에 자세히 설명) 다음을 수행할 수 있다.

    speeds = pd.DataFrame(
        [
            ("bird", "Falconiformes", 389.0),
            ("bird", "Psittaciformes", 24.0),
            ("mammal", "Carnivora", 80.2),
            ("mammal", "Primates", np.nan),
            ("mammal", "Carnivora", 58),
        ],
        index=["falcon", "parrot", "lion", "monkey", "leopard"],
        columns=("class", "order", "max_speed"),
    )
    
    speeds
    
    Out[2]:
              class           order  max_speed
    falcon     bird   Falconiformes      389.0
    parrot     bird  Psittaciformes       24.0
    lion     mammal       Carnivora       80.2
    monkey   mammal        Primates        NaN
    leopard  mammal       Carnivora       58.0
    
    grouped = speeds.groupby("class")
    
    grouped = speeds.groupby(["class", "order"])

    The mapping can be specified many different ways:

    • A Python function, to be called on each of the index labels.
    • A list or NumPy array of the same length as the index.
    • A dict or Series, providing a label -> group name mapping.
    • For DataFrame objects, a string indicating either a column name or an index level name to be used to group.
    • A list of any of the above things.

    매핑은 다양한 방법으로 지정할 수 있다.

    • 각 인덱스 레이블에 대해 호출되는 Python 함수이다.
    • 인덱스와 길이가 같은 리스트 또는 NumPy 배열이다.
    • 레이블 -> 그룹 이름 매핑을 제공하는 딕셔너리 또는 시리즈이다.
    • DataFrame 객체의 경우 그룹화하는 데 사용할 열 이름 또는 인덱스 수준 이름을 나타내는 문자열이다.
    • 위 항목의 리스트이다.

    Collectively we refer to the grouping objects as the keys. For example, consider the following DataFrame:

    집합적으로 그룹화시키는 개체를 키라고 한다. 예를 들어 다음 DataFrame을 고려해보자.

    Note

    A string passed to groupby may refer to either a column or an index level. If a string matches both a column name and an index level name, a ValueError will be raised.

    groupby에 전달된 문자열은 열이나 인덱스 수준을 참조할 수 있다. 문자열이 열 이름과 인덱스 수준 이름 모두와 일치하면 ValueError가 발생한다.

    df = pd.DataFrame(
        {
            "A": ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "foo"],
            "B": ["one", "one", "two", "three", "two", "two", "one", "three"],
            "C": np.random.randn(8),
            "D": np.random.randn(8),
        }
    )
    
    df
    Out[6]:
         A      B         C         D
    0  foo    one  0.469112 -0.861849
    1  bar    one -0.282863 -2.104569
    2  foo    two -1.509059 -0.494929
    3  bar  three -1.135632  1.071804
    4  foo    two  1.212112  0.721555
    5  bar    two -0.173215 -0.706771
    6  foo    one  0.119209 -1.039575
    7  foo  three -1.044236  0.271860

    On a DataFrame, we obtain a GroupBy object by calling groupby(). This method returns a pandas.api.typing.DataFrameGroupBy instance. We could naturally group by either the A or B columns, or both:

    DataFrame에서는 groupby()를 호출하여 GroupBy 객체를 얻는다. 이 메서드는 pandas.api.typing.DataFrameGroupBy 인스턴스를 반환한다. 자연스럽게 A나 B 열 또는 둘 다를 기준으로 그룹화할 수 있다.

    grouped = df.groupby("A")
    
    grouped = df.groupby("B")
    
    grouped = df.groupby(["A", "B"])

    Note

    df.groupby('A') is just syntactic sugar for df.groupby(df['A']).

    df.groupby('A')는 df.groupby(df['A'])의 간단한 구문이다.

    If we also have a MultiIndex on columns A and B, we can group by all the columns except the one we specify:

    열 A와 B에도 MultiIndex가 있는 경우 지정한 열을 제외한 모든 열을 기준으로 그룹화할 수 있다.

    df2 = df.set_index(["A", "B"])
    
    grouped = df2.groupby(level=df2.index.names.difference(["B"]))
    
    grouped.sum()
    Out[12]:
                C         D
    A
    bar -1.591710 -1.739537
    foo -0.752861 -1.402938

    The above GroupBy will split the DataFrame on its index (rows). To split by columns, first do a transpose:

    위의 GroupBy는 DataFrame을 해당 인덱스(행)로 분할한다. 열로 분할하려면 먼저 전치를 수행하라.

    def get_letter_type(letter):
        if letter.lower() in 'aeiou':
            return 'vowel'
        else:
            return 'consonant'
    
    grouped = df.T.groupby(get_letter_type)

    pandas Index objects support duplicate values. If a non-unique index is used as the group key in a groupby operation, all values for the same index value will be considered to be in one group and thus the output of aggregation functions will only contain unique index values:

    pandas Index 객체는 중복 값을 지원한다. 고유하지 않은 인덱스가 groupby 작업에서 그룹 키로 사용되는 경우 동일한 인덱스 값에 대한 모든 값은 하나의 그룹에 있는 것으로 간주되므로 집계 함수의 출력에는 고유 인덱스 값만 포함된다.

    index = [1, 2, 3, 1, 2, 3]
    
    s = pd.Series([1, 2, 3, 10, 20, 30], index=index)
    
    s
    Out[17]:
    1     1
    2     2
    3     3
    1    10
    2    20
    3    30
    dtype: int64
    
    grouped = s.groupby(level=0)
    
    grouped.first()
    Out[19]:
    1    1
    2    2
    3    3
    dtype: int64
    
    grouped.last()
    Out[20]:
    1    10
    2    20
    3    30
    dtype: int64
    
    grouped.sum()
    Out[21]:
    1    11
    2    22
    3    33
    dtype: int64

    Note that no splitting occurs until it’s needed. Creating the GroupBy object only verifies that you’ve passed a valid mapping.

    필요할 때까지는 분할이 발생하지 않는다. GroupBy 개체를 생성하면 유효한 매핑이 전달되었는지만 확인된다.

    Note

    Many kinds of complicated data manipulations can be expressed in terms of GroupBy operations (though it can’t be guaranteed to be the most efficient implementation). You can get quite creative with the label mapping functions.

    다양한 종류의 복잡한 데이터 조작을 GroupBy 작업으로 표현할 수 있다(가장 효율적인 구현이라고 보장할 수는 없음). 라벨 매핑 기능을 사용하면 창의력을 발휘할 수 있다.

    GroupBy sorting / GroupBy 정렬

    By default the group keys are sorted during the groupby operation. You may however pass sort=False for potential speedups. With sort=False the order among group-keys follows the order of appearance of the keys in the original dataframe:

    기본적으로 그룹 키는 groupby 작업 중에 정렬된다. 그러나 잠재적인 속도 향상을 위해 sort=False를 전달할 수 있다. sort=False를 사용하면 그룹 키 간의 순서는 원래 데이터 프레임에 키가 나타나는 순서를 따른다.

    df2 = pd.DataFrame({"X": ["B", "B", "A", "A"], "Y": [1, 2, 3, 4]})
    
    df2.groupby(["X"]).sum()
    Out[23]:
       Y
    X
    A  7
    B  3
    
    df2.groupby(["X"], sort=False).sum()
    Out[24]:
       Y
    X
    B  3
    A  7

    Note that groupby will preserve the order in which observations are sorted within each group. For example, the groups created by groupby() below are in the order they appeared in the original DataFrame:

    groupby는 각 그룹 내에서 관측값이 정렬되는 순서를 유지한다. 예를 들어 아래의 groupby()로 생성된 그룹은 원본 DataFrame에 표시된 순서대로 표시된다.

    df3 = pd.DataFrame({"X": ["A", "B", "A", "B"], "Y": [1, 4, 3, 2]})
    
    df3.groupby("X").get_group("A")
    Out[26]:
       X  Y
    0  A  1
    2  A  3
    
    df3.groupby(["X"]).get_group(("B",))
    Out[27]:
       X  Y
    1  B  4
    3  B  2

    GroupBy dropna

    By default NA values are excluded from group keys during the groupby operation. However, in case you want to include NA values in group keys, you could pass dropna=False to achieve it.

    기본적으로 NA 값은 groupby 작업 중에 그룹 키에서 제외된다. 그러나 그룹 키에 NA 값을 포함하려는 경우 dropna=False를 전달하여 이를 달성할 수 있다.

    df_list = [[1, 2, 3], [1, None, 4], [2, 1, 3], [1, 2, 2]]
    
    df_dropna = pd.DataFrame(df_list, columns=["a", "b", "c"])
    
    df_dropna
    Out[30]:
       a    b  c
    0  1  2.0  3
    1  1  NaN  4
    2  2  1.0  3
    3  1  2.0  2
    # Default ``dropna`` is set to True, which will exclude NaNs in keys
    df_dropna.groupby(by=["b"], dropna=True).sum()
    Out[31]:
         a  c
    b
    1.0  2  3
    2.0  2  5
    
    # In order to allow NaN in keys, set ``dropna`` to False
    df_dropna.groupby(by=["b"], dropna=False).sum()
    Out[32]:
         a  c
    b
    1.0  2  3
    2.0  2  5
    NaN  1  4

    The default setting of dropna argument is True which means NA are not included in group keys.

    dropna 인수의 기본 설정은 True이다. 이는 NA가 그룹 키에 포함되지 않음을 의미한다.

    GroupBy object attributes / GroupBy 개체 속성

    The groups attribute is a dictionary whose keys are the computed unique groups and corresponding values are the axis labels belonging to each group. In the above example we have:

    groups 속성은 키가 계산된 고유 그룹이고 해당 값이 각 그룹에 속하는 축 레이블인 딕셔너리이다. 위의 예에는 다음이 있다.

    df.groupby("A").groups
    Out[33]: {'bar': [1, 3, 5], 'foo': [0, 2, 4, 6, 7]}
    
    df.T.groupby(get_letter_type).groups
    Out[34]: {'consonant': ['B', 'C', 'D'], 'vowel': ['A']}

    Calling the standard Python len function on the GroupBy object returns the number of groups, which is the same as the length of the groups dictionary:

    GroupBy 객체에서 표준 Python len 함수를 호출하면 그룹 딕셔너리의 길이와 동일한 그룹 수를 반환한다.

    grouped = df.groupby(["A", "B"])
    
    grouped.groups
    Out[36]: {('bar', 'one'): [1], ('bar', 'three'): [3], ('bar', 'two'): [5], ('foo', 'one'): [0, 6], ('foo', 'three'): [7], ('foo', 'two'): [2, 4]}
    
    len(grouped)
    Out[37]: 6

    GroupBy will tab complete column names, GroupBy operations, and other attributes:

    GroupBy는 전체 열 이름, GroupBy 작업 및 기타 속성을 탭한다.

    n = 10
    
    weight = np.random.normal(166, 20, size=n)
    
    height = np.random.normal(60, 10, size=n)
    
    time = pd.date_range("1/1/2000", periods=n)
    
    gender = np.random.choice(["male", "female"], size=n)
    
    df = pd.DataFrame(
        {"height": height, "weight": weight, "gender": gender}, index=time
    )
    
    
    df
    Out[44]:
                   height      weight  gender
    2000-01-01  42.849980  157.500553    male
    2000-01-02  49.607315  177.340407    male
    2000-01-03  56.293531  171.524640    male
    2000-01-04  48.421077  144.251986  female
    2000-01-05  46.556882  152.526206    male
    2000-01-06  68.448851  168.272968  female
    2000-01-07  70.757698  136.431469    male
    2000-01-08  58.909500  176.499753  female
    2000-01-09  76.435631  174.094104  female
    2000-01-10  45.306120  177.540920    male
    
    gb = df.groupby("gender")
    gb.  # noqa: E225, E999
    gb.agg        gb.boxplot    gb.cummin     gb.describe   gb.filter     gb.get_group  gb.height     gb.last       gb.median     gb.ngroups    gb.plot       gb.rank       gb.std        gb.transform
    gb.aggregate  gb.count      gb.cumprod    gb.dtype      gb.first      gb.groups     gb.hist       gb.max        gb.min        gb.nth        gb.prod       gb.resample   gb.sum        gb.var
    gb.apply      gb.cummax     gb.cumsum     gb.fillna     gb.gender     gb.head       gb.indices    gb.mean       gb.name       gb.ohlc       gb.quantile   gb.size       gb.tail       gb.weight

    GroupBy with MultiIndex

    With hierarchically-indexed data, it’s quite natural to group by one of the levels of the hierarchy.

    Let’s create a Series with a two-level MultiIndex.

    계층적으로 인덱스된 데이터를 사용하면 계층 수준 중 하나로 그룹화하는 것이 매우 자연스럽다.

    2단계 MultiIndex를 사용하여 시리즈를 만들어 본다.

    arrays = [
        ["bar", "bar", "baz", "baz", "foo", "foo", "qux", "qux"],
        ["one", "two", "one", "two", "one", "two", "one", "two"],
    ]
    
    index = pd.MultiIndex.from_arrays(arrays, names=["first", "second"])
    
    s = pd.Series(np.random.randn(8), index=index)
    
    s
    Out[50]:
    first  second
    bar    one      -0.919854
           two      -0.042379
    baz    one       1.247642
           two      -0.009920
    foo    one       0.290213
           two       0.495767
    qux    one       0.362949
           two       1.548106
    dtype: float64

    We can then group by one of the levels in s.

    그런 다음 s의 수준 중 하나로 그룹화할 수 있다.

    grouped = s.groupby(level=0)
    
    grouped.sum()
    Out[52]:
    first
    bar   -0.962232
    baz    1.237723
    foo    0.785980
    qux    1.911055
    dtype: float64

    If the MultiIndex has names specified, these can be passed instead of the level number:

    MultiIndex에 지정된 이름이 있는 경우 레벨 번호 대신 이러한 이름을 전달할 수 있다.

    s.groupby(level="second").sum()
    Out[53]:
    second
    one    0.980950
    two    1.991575
    dtype: float64

    Grouping with multiple levels is supported.

    여러 수준의 그룹화가 지원된다.

    arrays = [
        ["bar", "bar", "baz", "baz", "foo", "foo", "qux", "qux"],
        ["doo", "doo", "bee", "bee", "bop", "bop", "bop", "bop"],
        ["one", "two", "one", "two", "one", "two", "one", "two"],
    ]
    
    index = pd.MultiIndex.from_arrays(arrays, names=["first", "second", "third"])
    
    s = pd.Series(np.random.randn(8), index=index)
    
    s
    Out[57]:
    first  second  third
    bar    doo     one     -1.131345
                   two     -0.089329
    baz    bee     one      0.337863
                   two     -0.945867
    foo    bop     one     -0.932132
                   two      1.956030
    qux    bop     one      0.017587
                   two     -0.016692
    dtype: float64
    
    s.groupby(level=["first", "second"]).sum()
    Out[58]:
    first  second
    bar    doo      -1.220674
    baz    bee      -0.608004
    foo    bop       1.023898
    qux    bop       0.000895
    dtype: float64

    Index level names may be supplied as keys.

    인덱스 수준 이름은 키로 제공될 수 있다.

    s.groupby(["first", "second"]).sum()
    Out[59]:
    first  second
    bar    doo      -1.220674
    baz    bee      -0.608004
    foo    bop       1.023898
    qux    bop       0.000895
    dtype: float64

    More on the sum function and aggregation later.

    나중에 합계 함수와 집계에 대해 자세히 알아보자.

    Grouping DataFrame with Index levels and columns / 인덱스 수준 및 열을 사용하여 DataFrame 그룹화

    A DataFrame may be grouped by a combination of columns and index levels. You can specify both column and index names, or use a Grouper.

    Let’s first create a DataFrame with a MultiIndex:

    DataFrame은 열과 인덱스 수준의 조합으로 그룹화될 수 있다. 열 이름과 인덱스 이름을 모두 지정하거나 그룹화 도구를 사용할 수 있다.

    먼저 MultiIndex를 사용하여 DataFrame을 생성해 본다.

    arrays = [
        ["bar", "bar", "baz", "baz", "foo", "foo", "qux", "qux"],
        ["one", "two", "one", "two", "one", "two", "one", "two"],
    ]
    
    index = pd.MultiIndex.from_arrays(arrays, names=["first", "second"])
    
    df = pd.DataFrame({"A": [1, 1, 1, 1, 2, 2, 3, 3], "B": np.arange(8)}, index=index)
    
    df
    Out[63]:
                  A  B
    first second
    bar   one     1  0
          two     1  1
    baz   one     1  2
          two     1  3
    foo   one     2  4
          two     2  5
    qux   one     3  6
          two     3  7

    Then we group df by the second index level and the A column.

    그런 다음 df를 두 번째 인덱스 수준과 A 열로 그룹화한다.

    df.groupby([pd.Grouper(level=1), "A"]).sum()
    Out[64]:
              B
    second A
    one    1  2
           2  4
           3  6
    two    1  4
           2  5
           3  7

    Index levels may also be specified by name.

    인덱스 수준은 이름으로 지정할 수도 있다.

    df.groupby([pd.Grouper(level="second"), "A"]).sum()
    Out[65]:
              B
    second A
    one    1  2
           2  4
           3  6
    two    1  4
           2  5
           3  7

    Index level names may be specified as keys directly to groupby.

    인덱스 수준 이름은 groupby에 직접 키로 지정될 수 있다.

    df.groupby(["second", "A"]).sum()
    Out[66]:
              B
    second A
    one    1  2
           2  4
           3  6
    two    1  4
           2  5
           3  7

    DataFrame column selection in GroupBy / GroupBy에서 DataFrame 열 선택

    Once you have created the GroupBy object from a DataFrame, you might want to do something different for each of the columns. Thus, by using [] on the GroupBy object in a similar way as the one used to get a column from a DataFrame, you can do:

    DataFrame에서 GroupBy 개체를 만든 후에는 각 열에 대해 다른 작업을 수행할 수 있다. 따라서 DataFrame에서 열을 가져오는 데 사용된 것과 비슷한 방식으로 GroupBy 개체에 []를 사용하면 다음을 수행할 수 있다.

    df = pd.DataFrame(
        {
            "A": ["foo", "bar", "foo", "bar", "foo", "bar", "foo", "foo"],
            "B": ["one", "one", "two", "three", "two", "two", "one", "three"],
            "C": np.random.randn(8),
            "D": np.random.randn(8),
        }
    )
    
    df
    Out[68]:
         A      B         C         D
    0  foo    one -0.575247  1.346061
    1  bar    one  0.254161  1.511763
    2  foo    two -1.143704  1.627081
    3  bar  three  0.215897 -0.990582
    4  foo    two  1.193555 -0.441652
    5  bar    two -0.077118  1.211526
    6  foo    one -0.408530  0.268520
    7  foo  three -0.862495  0.024580
    
    grouped = df.groupby(["A"])
    
    grouped_C = grouped["C"]
    
    grouped_D = grouped["D"]

    This is mainly syntactic sugar for the alternative, which is much more verbose:

    이것은 주로 대안에 대한 구문적 달콤함이며 훨씬 더 장황하다.

    df["C"].groupby(df["A"])
    Out[72]: 

    Additionally, this method avoids recomputing the internal grouping information derived from the passed key.

    You can also include the grouping columns if you want to operate on them.

    또한 이 방법은 전달된 키에서 파생된 내부 그룹화 정보를 다시 계산하는 것을 방지한다.

    그룹화 열에 대해 작업을 수행하려는 경우 그룹화 열을 포함할 수도 있다.

    grouped[["A", "B"]].sum()
    Out[73]:
                       A                  B
    A
    bar        barbarbar        onethreetwo
    foo  foofoofoofoofoo  onetwotwoonethree

    Iterating through groups / 그룹 순환

    With the GroupBy object in hand, iterating through the grouped data is very natural and functions similarly to itertools.groupby():

    GroupBy 객체를 사용하면 그룹화된 데이터를 반복하는 것이 매우 자연스럽고 itertools.groupby()와 유사하게 작동한다.

    grouped = df.groupby('A')
    
    for name, group in grouped:
        print(name)
        print(group)
    
    bar
         A      B         C         D
    1  bar    one  0.254161  1.511763
    3  bar  three  0.215897 -0.990582
    5  bar    two -0.077118  1.211526
    foo
         A      B         C         D
    0  foo    one -0.575247  1.346061
    2  foo    two -1.143704  1.627081
    4  foo    two  1.193555 -0.441652
    6  foo    one -0.408530  0.268520
    7  foo  three -0.862495  0.024580

    In the case of grouping by multiple keys, the group name will be a tuple:

    여러 키로 그룹화하는 경우 그룹 이름은 튜플이 된다.

    for name, group in df.groupby(['A', 'B']):
        print(name)
        print(group)
    
    ('bar', 'one')
         A    B         C         D
    1  bar  one  0.254161  1.511763
    ('bar', 'three')
         A      B         C         D
    3  bar  three  0.215897 -0.990582
    ('bar', 'two')
         A    B         C         D
    5  bar  two -0.077118  1.211526
    ('foo', 'one')
         A    B         C         D
    0  foo  one -0.575247  1.346061
    6  foo  one -0.408530  0.268520
    ('foo', 'three')
         A      B         C        D
    7  foo  three -0.862495  0.02458
    ('foo', 'two')
         A    B         C         D
    2  foo  two -1.143704  1.627081
    4  foo  two  1.193555 -0.441652

    See Iterating through groups.

    그룹 순환을 참조하라.

    Selecting a group / 그룹 선택

    A single group can be selected using DataFrameGroupBy.get_group():

    DataFrameGroupBy.get_group()을 사용하여 단일 그룹을 선택할 수 있다.

    grouped.get_group("bar")
    Out[77]:
         A      B         C         D
    1  bar    one  0.254161  1.511763
    3  bar  three  0.215897 -0.990582
    5  bar    two -0.077118  1.211526

    Or for an object grouped on multiple columns:

    또는 여러 열로 그룹화된 개체의 경우

    df.groupby(["A", "B"]).get_group(("bar", "one"))
    Out[78]:
         A    B         C         D
    1  bar  one  0.254161  1.511763

    Aggregation / 집계

    An aggregation is a GroupBy operation that reduces the dimension of the grouping object. The result of an aggregation is, or at least is treated as, a scalar value for each column in a group. For example, producing the sum of each column in a group of values.

    집계는 그룹화 개체의 차원을 줄이는 GroupBy 작업이다. 집계 결과는 그룹의 각 열에 대한 스칼라 값이거나 적어도 스칼라 값으로 처리된다. 예를 들어 값 그룹에 있는 각 열의 합계를 생성한다.

    animals = pd.DataFrame(
        {
            "kind": ["cat", "dog", "cat", "dog"],
            "height": [9.1, 6.0, 9.5, 34.0],
            "weight": [7.9, 7.5, 9.9, 198.0],
        }
    )
    
    animals
    Out[80]:
      kind  height  weight
    0  cat     9.1     7.9
    1  dog     6.0     7.5
    2  cat     9.5     9.9
    3  dog    34.0   198.0
    
    animals.groupby("kind").sum()
    Out[81]:
          height  weight
    kind
    cat     18.6    17.8
    dog     40.0   205.5

    In the result, the keys of the groups appear in the index by default. They can be instead included in the columns by passing as_index=False.

    결과적으로 그룹의 키가 기본적으로 인덱스에 나타난다. 대신 as_index=False를 전달하여 열에 포함할 수 있다.

    animals.groupby("kind", as_index=False).sum()
    Out[82]:
      kind  height  weight
    0  cat    18.6    17.8
    1  dog    40.0   205.5

    Built-in aggregation methods / 내장 집계 메서드

    Many common aggregations are built-in to GroupBy objects as methods. Of the methods listed below, those with a * do not have an efficient, GroupBy-specific, implementation.

    많은 공통 집계가 GroupBy 개체에 메서드로 내장되어 있다. 아래 나열된 메서드 중에서 *가 있는 메서드는 효율적인 GroupBy별 구현이 없다.

    Method Description
    any() Compute whether any of the values in the groups are truthy
    all() Compute whether all of the values in the groups are truthy
    count() Compute the number of non-NA values in the groups
    cov() * Compute the covariance of the groups
    first() Compute the first occurring value in each group
    idxmax() Compute the index of the maximum value in each group
    idxmin() Compute the index of the minimum value in each group
    last() Compute the last occurring value in each group
    max() Compute the maximum value in each group
    mean() Compute the mean of each group
    median() Compute the median of each group
    min() Compute the minimum value in each group
    nunique() Compute the number of unique values in each group
    prod() Compute the product of the values in each group
    quantile() Compute a given quantile of the values in each group
    sem() Compute the standard error of the mean of the values in each group
    size() Compute the number of values in each group
    skew() * Compute the skew of the values in each group
    std() Compute the standard deviation of the values in each group
    sum() Compute the sum of the values in each group
    var() Compute the variance of the values in each group
    메서드 설명
    any() 그룹의 값이 참인지 여부를 계산한다.
    all() 그룹의 모든 값이 참인지 여부를 계산한다.
    count() 그룹에서 NA가 아닌 값의 수를 계산한다.
    cov() * 그룹의 공분산(covariance) 계산
    first() 각 그룹에서 처음으로 나타나는 값을 계산한다.
    idxmax() 각 그룹의 최대값 인덱스를 계산한다.
    idxmin() 각 그룹의 최소값 인덱스를 계산한다.
    last() 각 그룹에서 마지막으로 발생한 값을 계산한다.
    max() 각 그룹의 최대값을 계산한다.
    mean() 각 그룹의 평균을 계산한다.
    median() 각 그룹의 중앙값 계산
    min() 각 그룹의 최소값을 계산한다.
    nunique() 각 그룹의 고유 값 수를 계산한다.
    prod() 각 그룹의 값의 곱을 계산한다.
    quantile() 각 그룹에 있는 값의 주어진 분위수를 계산한다.
    sem() 각 그룹의 값 평균의 표준 오차를 계산한다.
    size() 각 그룹의 값 수 계산
    skew() * 각 그룹에 있는 값의 편향을 계산한다.
    std() 각 그룹 값의 표준편차를 계산한다.
    sum() 각 그룹의 값 합계를 계산한다.
    var() 각 그룹에 있는 값의 분산을 계산한다.

    Some examples:

    몇 가지 예:

    df.groupby("A")[["C", "D"]].max()
    Out[83]:
                C         D
    A
    bar  0.254161  1.511763
    foo  1.193555  1.627081
    
    df.groupby(["A", "B"]).mean()
    Out[84]:
                      C         D
    A   B
    bar one    0.254161  1.511763
        three  0.215897 -0.990582
        two   -0.077118  1.211526
    foo one   -0.491888  0.807291
        three -0.862495  0.024580
        two    0.024925  0.592714

    Another aggregation example is to compute the size of each group. This is included in GroupBy as the size method. It returns a Series whose index consists of the group names and the values are the sizes of each group.

    또 다른 집계 예는 각 그룹의 크기를 계산하는 것이다. 이는 size method로 GroupBy에 포함된다. 인덱스가 그룹 이름으로 구성되고 값이 각 그룹의 크기인 시리즈를 반환한다.

    grouped = df.groupby(["A", "B"])
    
    grouped.size()
    Out[86]:
    A    B
    bar  one      1
         three    1
         two      1
    foo  one      2
         three    1
         two      2
    dtype: int64

    While the DataFrameGroupBy.describe() method is not itself a reducer, it can be used to conveniently produce a collection of summary statistics about each of the groups.

    DataFrameGroupBy.describe() 메서드 자체는 reducer가 아니지만 각 그룹에 대한 요약 통계 모음을 편리하게 생성하는 데 사용할 수 있다.

    grouped.describe()
    Out[87]:
                  C                      ...         D
              count      mean       std  ...       50%       75%       max
    A   B                                ...
    bar one     1.0  0.254161       NaN  ...  1.511763  1.511763  1.511763
        three   1.0  0.215897       NaN  ... -0.990582 -0.990582 -0.990582
        two     1.0 -0.077118       NaN  ...  1.211526  1.211526  1.211526
    foo one     2.0 -0.491888  0.117887  ...  0.807291  1.076676  1.346061
        three   1.0 -0.862495       NaN  ...  0.024580  0.024580  0.024580
        two     2.0  0.024925  1.652692  ...  0.592714  1.109898  1.627081
    
    [6 rows x 16 columns]

    Another aggregation example is to compute the number of unique values of each group. This is similar to the DataFrameGroupBy.value_counts() function, except that it only counts the number of unique values.

    또 다른 집계 예는 각 그룹의 고유 값 수를 계산하는 것이다. 이는 고유한 값의 개수만 계산한다는 점을 제외하면 DataFrameGroupBy.value_counts() 함수와 유사하다.

    ll = [['foo', 1], ['foo', 2], ['foo', 2], ['bar', 1], ['bar', 1]]
    
    df4 = pd.DataFrame(ll, columns=["A", "B"])
    
    df4
    Out[90]:
         A  B
    0  foo  1
    1  foo  2
    2  foo  2
    3  bar  1
    4  bar  1
    
    df4.groupby("A")["B"].nunique()
    Out[91]:
    A
    bar    1
    foo    2
    Name: B, dtype: int64

    Note

    Aggregation functions will not return the groups that you are aggregating over as named columns when as_index=True, the default. The grouped columns will be the indices of the returned object.

    Passing as_index=False will return the groups that you are aggregating over as named columns, regardless if they are named indices or columns in the inputs.

    as_index=True(기본값)인 경우 집계 함수는 집계 중인 그룹을 명명된 열로 반환하지 않는다. 그룹화된 열은 반환된 개체의 인덱스가 된다.

    as_index=False를 전달하면 입력의 명명된 인덱스 또는 열인지 여부에 관계없이 집계 중인 그룹을 명명된 열로 반환한다.

    The aggregate() method

    Note

    The aggregate() method can accept many different types of inputs. This section details using string aliases for various GroupBy methods; other inputs are detailed in the sections below.

    aggregate() 메서드는 다양한 유형의 입력을 받아들일 수 있다. 이 섹션에서는 다양한 GroupBy 메서드에 대한 문자열 별칭 사용에 대해 자세히 설명한다. 다른 입력은 아래 섹션에 자세히 설명되어 있다.

    Any reduction method that pandas implements can be passed as a string to aggregate(). Users are encouraged to use the shorthand, agg. It will operate as if the corresponding method was called.

    팬더가 구현하는 모든 축소 방법은 문자열로 aggregate()에 전달될 수 있다. 사용자는 agg라는 약어를 사용하는 것이 좋다. 해당 메소드가 호출된 것처럼 동작한다.

    grouped = df.groupby("A")
    
    grouped[["C", "D"]].aggregate("sum")
    Out[93]:
                C         D
    A
    bar  0.392940  1.732707
    foo -1.796421  2.824590
    
    grouped = df.groupby(["A", "B"])
    
    grouped.agg("sum")
    Out[95]:
                      C         D
    A   B
    bar one    0.254161  1.511763
        three  0.215897 -0.990582
        two   -0.077118  1.211526
    foo one   -0.983776  1.614581
        three -0.862495  0.024580
        two    0.049851  1.185429

    The result of the aggregation will have the group names as the new index. In the case of multiple keys, the result is a MultiIndex by default. As mentioned above, this can be changed by using the as_index option:

    집계 결과에는 그룹 이름이 새 인덱스로 사용된다. 키가 여러 개인 경우 결과는 기본적으로 MultiIndex이다. 위에서 언급한 것처럼 이는 as_index 옵션을 사용하여 변경할 수 있다.

    grouped = df.groupby(["A", "B"], as_index=False)
    
    grouped.agg("sum")
    Out[97]:
         A      B         C         D
    0  bar    one  0.254161  1.511763
    1  bar  three  0.215897 -0.990582
    2  bar    two -0.077118  1.211526
    3  foo    one -0.983776  1.614581
    4  foo  three -0.862495  0.024580
    5  foo    two  0.049851  1.185429
    
    df.groupby("A", as_index=False)[["C", "D"]].agg("sum")
    Out[98]:
         A         C         D
    0  bar  0.392940  1.732707
    1  foo -1.796421  2.824590

    Note that you could use the DataFrame.reset_index() DataFrame function to achieve the same result as the column names are stored in the resulting MultiIndex, although this will make an extra copy.

    DataFrame.reset_index() DataFrame 함수를 사용하면 열 이름이 결과 MultiIndex에 저장되는 것과 동일한 결과를 얻을 수 있지만 이로 인해 추가 복사본이 만들어진다.

    df.groupby(["A", "B"]).agg("sum").reset_index()
    Out[99]:
         A      B         C         D
    0  bar    one  0.254161  1.511763
    1  bar  three  0.215897 -0.990582
    2  bar    two -0.077118  1.211526
    3  foo    one -0.983776  1.614581
    4  foo  three -0.862495  0.024580
    5  foo    two  0.049851  1.185429

    Aggregation with User-Defined Functions / 사용자 정의 함수를 사용한 집계

    Users can also provide their own User-Defined Functions (UDFs) for custom aggregations.

    사용자는 사용자 정의 집계를 위해 자체 UDF(사용자 정의 함수)를 제공할 수도 있다.

    Warning

    When aggregating with a UDF, the UDF should not mutate the provided Series. See Mutating with User Defined Function (UDF) methods for more information.

     

    UDF로 집계할 때 UDF는 제공된 시리즈를 변경해서는 안 된다. 자세한 내용은 사용자 정의 함수(UDF) 메서드로 변경을 참조하라.

    Note

    Aggregating with a UDF is often less performant than using the pandas built-in methods on GroupBy. Consider breaking up a complex operation into a chain of operations that utilize the built-in methods.

    UDF를 사용한 집계는 GroupBy에서 pandas 내장 메서드를 사용하는 것보다 성능이 떨어지는 경우가 많다. 복잡한 작업을 기본 제공 메서드를 활용하는 작업 체인으로 나누는 것을 고려해보자.

    animals
    Out[100]:
      kind  height  weight
    0  cat     9.1     7.9
    1  dog     6.0     7.5
    2  cat     9.5     9.9
    3  dog    34.0   198.0
    
    animals.groupby("kind")[["height"]].agg(lambda x: set(x))
    Out[101]:
               height
    kind
    cat    {9.1, 9.5}
    dog   {34.0, 6.0}

    The resulting dtype will reflect that of the aggregating function. If the results from different groups have different dtypes, then a common dtype will be determined in the same way as DataFrame construction.

    결과 dtype은 집계 함수의 dtype을 반영한다. 서로 다른 그룹의 결과에 서로 다른 dtype이 있는 경우 DataFrame 구성과 동일한 방식으로 공통 dtype이 결정된다.

    animals.groupby("kind")[["height"]].agg(lambda x: x.astype(int).sum())
    Out[102]:
          height
    kind
    cat       18
    dog       40

    Applying multiple functions at once / 여러 기능을 한번에 적용하기

    On a grouped Series, you can pass a list or dict of functions to SeriesGroupBy.agg(), outputting a DataFrame:

    그룹화된 Series에서는 함수 리스트나 딕셔너리를 SeriesGroupBy.agg()에 전달하여 DataFrame을 출력할 수 있다.

    grouped = df.groupby("A")
    
    grouped["C"].agg(["sum", "mean", "std"])
    Out[104]:
              sum      mean       std
    A
    bar  0.392940  0.130980  0.181231
    foo -1.796421 -0.359284  0.912265

    On a grouped DataFrame, you can pass a list of functions to DataFrameGroupBy.agg() to aggregate each column, which produces an aggregated result with a hierarchical column index:

    그룹화된 DataFrame에서는 함수 리스트을 DataFrameGroupBy.agg()에 전달하여 각 열을 집계할 수 있으며, 그러면 계층적 열 인덱스가 포함된 집계 결과가 생성된다.

    grouped[["C", "D"]].agg(["sum", "mean", "std"])
    Out[105]:
                C                             D
              sum      mean       std       sum      mean       std
    A
    bar  0.392940  0.130980  0.181231  1.732707  0.577569  1.366330
    foo -1.796421 -0.359284  0.912265  2.824590  0.564918  0.884785

    The resulting aggregations are named after the functions themselves. If you need to rename, then you can add in a chained operation for a Series like this:

    결과 집계의 이름은 함수 자체의 이름을 따서 지정된다. 이름을 바꿔야 하는 경우 다음과 같이 시리즈에 대한 연결 작업을 추가할 수 있다.

    (
        grouped["C"]
        .agg(["sum", "mean", "std"])
        .rename(columns={"sum": "foo", "mean": "bar", "std": "baz"})
    )
    
    Out[106]:
              foo       bar       baz
    A
    bar  0.392940  0.130980  0.181231
    foo -1.796421 -0.359284  0.912265

    For a grouped DataFrame, you can rename in a similar manner:

    그룹화된 DataFrame의 경우 비슷한 방식으로 이름을 바꿀 수 있다.

    (
        grouped[["C", "D"]].agg(["sum", "mean", "std"]).rename(
            columns={"sum": "foo", "mean": "bar", "std": "baz"}
        )
    )
    
    Out[107]:
                C                             D
              foo       bar       baz       foo       bar       baz
    A
    bar  0.392940  0.130980  0.181231  1.732707  0.577569  1.366330
    foo -1.796421 -0.359284  0.912265  2.824590  0.564918  0.884785

    Note

    In general, the output column names should be unique, but pandas will allow you apply to the same function (or two functions with the same name) to the same column.

    일반적으로 출력 열 이름은 고유해야 하지만 Pandas에서는 동일한 열에 동일한 함수(또는 동일한 이름을 가진 두 개의 함수)를 적용할 수 있다.

    grouped["C"].agg(["sum", "sum"])
    Out[108]:
              sum       sum
    A
    bar  0.392940  0.392940
    foo -1.796421 -1.796421

    pandas also allows you to provide multiple lambdas. In this case, pandas will mangle the name of the (nameless) lambda functions, appending `_` to each subsequent lambda.

    pandas를 사용하면 여러 람다를 제공할 수도 있다. 이 경우 팬더는 (이름 없는) 람다 함수의 이름을 뒤섞어 각 후속 람다에 `_`를 추가한다.

    grouped["C"].agg([lambda x: x.max() - x.min(), lambda x: x.median() - x.mean()])
    Out[109]:
           
    A
    bar    0.331279    0.084917
    foo    2.337259   -0.215962

    Named aggregation / 명명된 집계

    To support column-specific aggregation with control over the output column names, pandas accepts the special syntax in DataFrameGroupBy.agg() and SeriesGroupBy.agg(), known as “named aggregation”, where

    • The keywords are the output column names
    • The values are tuples whose first element is the column to select and the second element is the aggregation to apply to that column. pandas provides the NamedAgg namedtuple with the fields ['column', 'aggfunc'] to make it clearer what the arguments are. As usual, the aggregation can be a callable or a string alias.

    출력 열 이름을 제어하여 열별 집계를 지원하기 위해 pandas는 "이름이 지정된 집계"로 알려진 DataFrameGroupBy.agg() 및 SeriesGroupBy.agg()의 특수 구문을 허용한다.

    • 키워드는 출력 열 이름이다.
    • 값은 첫 번째 요소가 선택할 열이고 두 번째 요소가 해당 열에 적용할 집계인 튜플이다. pandas는 인수가 무엇인지 더 명확하게 하기 위해 ['column', 'aggfunc'] 필드와 함께 NamedAgg 네임드튜플을 제공한다. 평소와 같이 집계는 호출 가능 항목 또는 문자열 별칭일 수 있다.
    animals
    Out[110]:
      kind  height  weight
    0  cat     9.1     7.9
    1  dog     6.0     7.5
    2  cat     9.5     9.9
    3  dog    34.0   198.0
    
    animals.groupby("kind").agg(
        min_height=pd.NamedAgg(column="height", aggfunc="min"),
        max_height=pd.NamedAgg(column="height", aggfunc="max"),
        average_weight=pd.NamedAgg(column="weight", aggfunc="mean"),
    )
    
    Out[111]:
          min_height  max_height  average_weight
    kind
    cat          9.1         9.5            8.90
    dog          6.0        34.0          102.75

    NamedAgg is just a namedtuple. Plain tuples are allowed as well.

    NamedAgg는 단지 네임드 튜플이다. 일반 튜플도 허용된다.

    animals.groupby("kind").agg(
        min_height=("height", "min"),
        max_height=("height", "max"),
        average_weight=("weight", "mean"),
    )
    
    Out[112]:
          min_height  max_height  average_weight
    kind
    cat          9.1         9.5            8.90
    dog          6.0        34.0          102.75

    If the column names you want are not valid Python keywords, construct a dictionary and unpack the keyword arguments

    원하는 열 이름이 유효한 Python 키워드가 아닌 경우 딕셔너리를 구성하고 키워드 인수를 언팩한다.

    animals.groupby("kind").agg(
        **{
            "total weight": pd.NamedAgg(column="weight", aggfunc="sum")
        }
    )
    
    Out[113]:
          total weight
    kind
    cat           17.8
    dog          205.5

    When using named aggregation, additional keyword arguments are not passed through to the aggregation functions; only pairs of (column, aggfunc) should be passed as **kwargs. If your aggregation functions require additional arguments, apply them partially with functools.partial().

    Named aggregation is also valid for Series groupby aggregations. In this case there’s no column selection, so the values are just the functions.

    명명된 집계를 사용하는 경우 추가 키워드 인수가 집계 함수로 전달되지 않는다. (column, aggfunc) 쌍만 **kwargs로 전달되어야 한다. 집계 함수에 추가 인수가 필요한 경우 functools.partial()을 사용하여 부분적으로 적용하라.

    명명된 집계는 시리즈 그룹별 집계에도 유효하다. 이 경우 열 선택이 없으므로 값은 단지 함수일 뿐이다.

    animals.groupby("kind").height.agg(
        min_height="min",
        max_height="max",
    )
    
    Out[114]:
          min_height  max_height
    kind
    cat          9.1         9.5
    dog          6.0        34.0

    Applying different functions to DataFrame columns / DataFrame 열에 다양한 기능 적용

    By passing a dict to aggregate you can apply a different aggregation to the columns of a DataFrame:

    집계에 딕셔너리를 전달하면 DataFrame의 열에 다른 집계를 적용할 수 있다.

    grouped.agg({"C": "sum", "D": lambda x: np.std(x, ddof=1)})
    Out[115]:
                C         D
    A
    bar  0.392940  1.366330
    foo -1.796421  0.884785

    The function names can also be strings. In order for a string to be valid it must be implemented on GroupBy:

    함수 이름은 문자열일 수도 있다. 문자열이 유효하려면 GroupBy에서 구현되어야 한다.

    grouped.agg({"C": "sum", "D": "std"})
    Out[116]:
                C         D
    A
    bar  0.392940  1.366330
    foo -1.796421  0.884785

    Transformation / 변환

    A transformation is a GroupBy operation whose result is indexed the same as the one being grouped. Common examples include cumsum() and diff().

    변환은 결과가 그룹화되는 것과 동일하게 인덱싱되는 GroupBy 작업이다. 일반적인 예로는 cumsum() 및 diff()가 있다.

    speeds
    Out[117]:
              class           order  max_speed
    falcon     bird   Falconiformes      389.0
    parrot     bird  Psittaciformes       24.0
    lion     mammal       Carnivora       80.2
    monkey   mammal        Primates        NaN
    leopard  mammal       Carnivora       58.0
    
    grouped = speeds.groupby("class")["max_speed"]
    
    grouped.cumsum()
    Out[119]:
    falcon     389.0
    parrot     413.0
    lion        80.2
    monkey       NaN
    leopard    138.2
    Name: max_speed, dtype: float64
    
    grouped.diff()
    Out[120]:
    falcon       NaN
    parrot    -365.0
    lion         NaN
    monkey       NaN
    leopard      NaN
    Name: max_speed, dtype: float64

    Unlike aggregations, the groupings that are used to split the original object are not included in the result.

    집계와 달리 원본 개체를 분할하는 데 사용된 그룹화는 결과에 포함되지 않는다.

    Note

    Since transformations do not include the groupings that are used to split the result, the arguments as_index and sort in DataFrame.groupby() and Series.groupby() have no effect.

    변환에는 결과를 분할하는 데 사용되는 그룹화가 포함되지 않으므로 DataFrame.groupby() 및 Series.groupby()의 as_index 및 sort 인수는 효과가 없다.

    A common use of a transformation is to add the result back into the original DataFrame.

    변환의 일반적인 용도는 결과를 원래 DataFrame에 다시 추가하는 것이다.

    result = speeds.copy()
    
    result["cumsum"] = grouped.cumsum()
    
    result["diff"] = grouped.diff()
    
    result
    Out[124]:
              class           order  max_speed  cumsum   diff
    falcon     bird   Falconiformes      389.0   389.0    NaN
    parrot     bird  Psittaciformes       24.0   413.0 -365.0
    lion     mammal       Carnivora       80.2    80.2    NaN
    monkey   mammal        Primates        NaN     NaN    NaN
    leopard  mammal       Carnivora       58.0   138.2    NaN

    Built-in transformation methods / 내장된 변환 메서드

    The following methods on GroupBy act as transformations.

    GroupBy의 다음 메서드는 변환 역할을 한다.

    Method Description
    bfill() Back fill NA values within each group
    cumcount() Compute the cumulative count within each group
    cummax() Compute the cumulative max within each group
    cummin() Compute the cumulative min within each group
    cumprod() Compute the cumulative product within each group
    cumsum() Compute the cumulative sum within each group
    diff() Compute the difference between adjacent values within each group
    ffill() Forward fill NA values within each group
    pct_change() Compute the percent change between adjacent values within each group
    rank() Compute the rank of each value within each group
    shift() Shift values up or down within each group
    방법 설명
    bfill() 각 그룹 내의 NA 값 채우기
    cumcount() 각 그룹 내의 누적 개수를 계산한다.
    cummax() 각 그룹 내 누적 최대값 계산
    cummin() 각 그룹 내의 누적 최소값을 계산한다.
    cumprod() 각 그룹 내의 누적 곱을 계산한다.
    cumsum() 각 그룹 내의 누적 합계를 계산한다.
    diff() 각 그룹 내 인접한 값 간의 차이를 계산한다.
    ffill() 각 그룹 내에서 NA 값을 정방향으로 채우기
    pct_change() 각 그룹 내 인접한 값 사이의 변화율을 계산한다.
    rank() 각 그룹 내 각 값의 순위를 계산한다.
    shift() 각 그룹 내에서 값을 위 또는 아래로 이동

    In addition, passing any built-in aggregation method as a string to transform() (see the next section) will broadcast the result across the group, producing a transformed result. If the aggregation method has an efficient implementation, this will be performant as well.

    또한 내장 집계 메서드를 문자열로 transform()(다음 섹션 참조)에 전달하면 그룹 전체에 결과가 브로드캐스팅되어 변환된 결과가 생성된다. 집계 방법에 효율적인 구현이 있으면 이 방법도 성능이 좋다.

    The transform() method

    Similar to the aggregation method, the transform() method can accept string aliases to the built-in transformation methods in the previous section. It can also accept string aliases to the built-in aggregation methods. When an aggregation method is provided, the result will be broadcast across the group.

    집계 메서드와 유사하게, transform() 메서드는 이전 섹션의 내장 변환 메서드에 대한 문자열 별칭을 허용할 수 있다. 또한 내장된 집계 방법에 대한 문자열 별칭을 허용할 수도 있다. 집계 방법이 제공되면 결과가 그룹 전체에 브로드캐스팅된다.

    speeds
    Out[125]:
              class           order  max_speed
    falcon     bird   Falconiformes      389.0
    parrot     bird  Psittaciformes       24.0
    lion     mammal       Carnivora       80.2
    monkey   mammal        Primates        NaN
    leopard  mammal       Carnivora       58.0
    
    grouped = speeds.groupby("class")[["max_speed"]]
    
    grouped.transform("cumsum")
    Out[127]:
             max_speed
    falcon       389.0
    parrot       413.0
    lion          80.2
    monkey         NaN
    leopard      138.2
    
    grouped.transform("sum")
    Out[128]:
             max_speed
    falcon       413.0
    parrot       413.0
    lion         138.2
    monkey       138.2
    leopard      138.2

    In addition to string aliases, the transform() method can also accept User-Defined Functions (UDFs). The UDF must:

    • Return a result that is either the same size as the group chunk or broadcastable to the size of the group chunk (e.g., a scalar, grouped.transform(lambda x: x.iloc[-1])).
    • Operate column-by-column on the group chunk. The transform is applied to the first group chunk using chunk.apply.
    • Not perform in-place operations on the group chunk. Group chunks should be treated as immutable, and changes to a group chunk may produce unexpected results. See Mutating with User Defined Function (UDF) methods for more information.
    • (Optionally) operates on all columns of the entire group chunk at once. If this is supported, a fast path is used starting from the second chunk.

    문자열 별칭 외에도 변환() 메서드는 UDF(사용자 정의 함수)를 허용할 수도 있다. UDF는 다음을 충족해야 한다.

    • 그룹 청크와 동일한 크기이거나 그룹 청크의 크기로 브로드캐스팅 가능한 결과를 반환한다(예: 스칼라, grouped.transform(lambda x: x.iloc[-1])).
    • 그룹 청크에서 열별로 작업한다. 변환은 chunk.apply를 사용하여 첫 번째 그룹 청크에 적용된다.
    • 그룹 청크에서는 내부 작업을 수행하지 않는다. 그룹 청크는 불변으로 처리되어야 하며, 그룹 청크를 변경하면 예상치 못한 결과가 발생할 수 있다. 자세한 내용은 사용자 정의 함수(UDF) 메서드로 변경을 참조하라.
    • (선택적으로) 전체 그룹 청크의 모든 열에서 한 번에 작동한다. 이것이 지원되면 두 번째 청크부터 빠른 경로가 사용된다.

    Note

    Transforming by supplying transform with a UDF is often less performant than using the built-in methods on GroupBy. Consider breaking up a complex operation into a chain of operations that utilize the built-in methods.

    All of the examples in this section can be made more performant by calling built-in methods instead of using UDFs. See below for examples.

    UDF로 변환을 제공하여 변환하는 것은 GroupBy에 내장된 메서드를 사용하는 것보다 성능이 떨어지는 경우가 많다. 복잡한 작업을 기본 제공 메서드를 활용하는 작업 체인으로 나누는 것을 고려해보자.

    이 섹션의 모든 예제는 UDF를 사용하는 대신 내장 메소드를 호출하여 성능을 더욱 향상시킬 수 있다. 예시는 아래를 참조하라.

    Changed in version 2.0.0: When using .transform on a grouped DataFrame and the transformation function returns a DataFrame, pandas now aligns the result’s index with the input’s index. You can call .to_numpy() within the transformation function to avoid alignment.

    버전 2.0.0에서 변경됨: 그룹화된 DataFrame에서 .transform을 사용하고 변환 함수가 DataFrame을 반환하면 pandas는 이제 결과 인덱스를 입력 인덱스에 정렬한다. 정렬을 방지하려면 변환 함수 내에서 .to_numpy()를 호출할 수 있다.

    Similar to The aggregate() method, the resulting dtype will reflect that of the transformation function. If the results from different groups have different dtypes, then a common dtype will be determined in the same way as DataFrame construction.

    Suppose we wish to standardize the data within each group:

    aggregate() 메서드와 유사하게 결과 dtype은 변환 함수의 dtype을 반영한다. 서로 다른 그룹의 결과에 서로 다른 dtype이 있는 경우 DataFrame 구성과 동일한 방식으로 공통 dtype이 결정된다.

    각 그룹 내의 데이터를 표준화한다고 가정해 본다.

    index = pd.date_range("10/1/1999", periods=1100)
    
    ts = pd.Series(np.random.normal(0.5, 2, 1100), index)
    
    ts = ts.rolling(window=100, min_periods=100).mean().dropna()
    
    ts.head()
    Out[132]:
    2000-01-08    0.779333
    2000-01-09    0.778852
    2000-01-10    0.786476
    2000-01-11    0.782797
    2000-01-12    0.798110
    Freq: D, dtype: float64
    
    ts.tail()
    Out[133]:
    2002-09-30    0.660294
    2002-10-01    0.631095
    2002-10-02    0.673601
    2002-10-03    0.709213
    2002-10-04    0.719369
    Freq: D, dtype: float64
    
    transformed = ts.groupby(lambda x: x.year).transform(
        lambda x: (x - x.mean()) / x.std()
    )

    We would expect the result to now have mean 0 and standard deviation 1 within each group (up to floating-point error), which we can easily check:

    이제 결과는 각 그룹 내에서 평균 0과 표준 편차 1(부동 소수점 오류까지)을 가질 것으로 예상되며 이를 쉽게 확인할 수 있다.

    # Original Data
    
    grouped = ts.groupby(lambda x: x.year)
    
    grouped.mean()
    Out[136]:
    2000    0.442441
    2001    0.526246
    2002    0.459365
    dtype: float64
    
    grouped.std()
    Out[137]:
    2000    0.131752
    2001    0.210945
    2002    0.128753
    dtype: float64
    
    # Transformed Data
    
    grouped_trans = transformed.groupby(lambda x: x.year)
    
    grouped_trans.mean()
    Out[139]:
    2000   -4.870756e-16
    2001   -1.545187e-16
    2002    4.136282e-16
    dtype: float64
    
    grouped_trans.std()
    Out[140]:
    2000    1.0
    2001    1.0
    2002    1.0
    dtype: float64

    We can also visually compare the original and transformed data sets.

    원본 데이터 세트와 변환된 데이터 세트를 시각적으로 비교할 수도 있다.

    compare = pd.DataFrame({"Original": ts, "Transformed": transformed})
    
    compare.plot()
    Out[142]: 

    https://pandas.pydata.org/pandas-docs/stable/_images/groupby_transform_plot.png

    Transformation functions that have lower dimension outputs are broadcast to match the shape of the input array.

    더 낮은 차원 출력을 갖는 변환 함수는 입력 배열의 모양과 일치하도록 브로드캐스트된다.

    ts.groupby(lambda x: x.year).transform(lambda x: x.max() - x.min())
    Out[143]:
    2000-01-08    0.623893
    2000-01-09    0.623893
    2000-01-10    0.623893
    2000-01-11    0.623893
    2000-01-12    0.623893
                    ...
    2002-09-30    0.558275
    2002-10-01    0.558275
    2002-10-02    0.558275
    2002-10-03    0.558275
    2002-10-04    0.558275
    Freq: D, Length: 1001, dtype: float64

    Another common data transform is to replace missing data with the group mean.

    또 다른 일반적인 데이터 변환은 누락된 데이터를 그룹 평균으로 바꾸는 것이다.

    cols = ["A", "B", "C"]
    
    values = np.random.randn(1000, 3)
    
    values[np.random.randint(0, 1000, 100), 0] = np.nan
    
    values[np.random.randint(0, 1000, 50), 1] = np.nan
    
    values[np.random.randint(0, 1000, 200), 2] = np.nan
    
    data_df = pd.DataFrame(values, columns=cols)
    
    data_df
    Out[150]:
                A         B         C
    0    1.539708 -1.166480  0.533026
    1    1.302092 -0.505754       NaN
    2   -0.371983  1.104803 -0.651520
    3   -1.309622  1.118697 -1.161657
    4   -1.924296  0.396437  0.812436
    ..        ...       ...       ...
    995 -0.093110  0.683847 -0.774753
    996 -0.185043  1.438572       NaN
    997 -0.394469 -0.642343  0.011374
    998 -1.174126  1.857148       NaN
    999  0.234564  0.517098  0.393534
    
    [1000 rows x 3 columns]
    
    countries = np.array(["US", "UK", "GR", "JP"])
    
    key = countries[np.random.randint(0, 4, 1000)]
    
    grouped = data_df.groupby(key)
    
    # Non-NA count in each group
    grouped.count()
    Out[154]:
          A    B    C
    GR  209  217  189
    JP  240  255  217
    UK  216  231  193
    US  239  250  217
    
    transformed = grouped.transform(lambda x: x.fillna(x.mean()))

    We can verify that the group means have not changed in the transformed data, and that the transformed data contains no NAs.

    변환된 데이터에서 그룹 평균이 변경되지 않았으며 변환된 데이터에 NA가 포함되어 있지 않음을 확인할 수 있다.

    grouped_trans = transformed.groupby(key)
    
    grouped.mean()  # original group means
    Out[157]:
               A         B         C
    GR -0.098371 -0.015420  0.068053
    JP  0.069025  0.023100 -0.077324
    UK  0.034069 -0.052580 -0.116525
    US  0.058664 -0.020399  0.028603
    
    grouped_trans.mean()  # transformation did not change group means
    Out[158]:
               A         B         C
    GR -0.098371 -0.015420  0.068053
    JP  0.069025  0.023100 -0.077324
    UK  0.034069 -0.052580 -0.116525
    US  0.058664 -0.020399  0.028603
    
    grouped.count()  # original has some missing data points
    Out[159]:
          A    B    C
    GR  209  217  189
    JP  240  255  217
    UK  216  231  193
    US  239  250  217
    
    grouped_trans.count()  # counts after transformation
    Out[160]:
          A    B    C
    GR  228  228  228
    JP  267  267  267
    UK  247  247  247
    US  258  258  258
    
    grouped_trans.size()  # Verify non-NA count equals group size
    Out[161]:
    GR    228
    JP    267
    UK    247
    US    258
    dtype: int64

    As mentioned in the note above, each of the examples in this section can be computed more efficiently using built-in methods. In the code below, the inefficient way using a UDF is commented out and the faster alternative appears below.

    위의 참고 사항에서 언급했듯이 이 섹션의 각 예제는 내장된 메서드를 사용하여 더 효율적으로 계산할 수 있다. 아래 코드에서는 UDF를 사용하는 비효율적인 방법이 주석 처리되어 있으며 더 빠른 대안이 아래에 나와 있다.

    # result = ts.groupby(lambda x: x.year).transform(
    #     lambda x: (x - x.mean()) / x.std()
    # )
    grouped = ts.groupby(lambda x: x.year)
    
    result = (ts - grouped.transform("mean")) / grouped.transform("std")
    
    # result = ts.groupby(lambda x: x.year).transform(lambda x: x.max() - x.min())
    grouped = ts.groupby(lambda x: x.year)
    
    result = grouped.transform("max") - grouped.transform("min")
    
    # grouped = data_df.groupby(key)
    # result = grouped.transform(lambda x: x.fillna(x.mean()))
    grouped = data_df.groupby(key)
    
    result = data_df.fillna(grouped.transform("mean"))

    Window and resample operations / 윈도우 및 리샘플링 작업

    It is possible to use resample(), expanding() and rolling() as methods on groupbys.

    The example below will apply the rolling() method on the samples of the column B, based on the groups of column A.

    groupbys의 메소드로 resample(), expanding() 및 rolling()을 사용할 수 있다.

    아래 예에서는 A열의 그룹을 기준으로 B열의 샘플에 rolling() 메서드를 적용한다.

    df_re = pd.DataFrame({"A": [1] * 10 + [5] * 10, "B": np.arange(20)})
    
    df_re
    Out[169]:
        A   B
    0   1   0
    1   1   1
    2   1   2
    3   1   3
    4   1   4
    .. ..  ..
    15  5  15
    16  5  16
    17  5  17
    18  5  18
    19  5  19
    
    [20 rows x 2 columns]
    
    df_re.groupby("A").rolling(4).B.mean()
    Out[170]:
    A
    1  0      NaN
       1      NaN
       2      NaN
       3      1.5
       4      2.5
             ...
    5  15    13.5
       16    14.5
       17    15.5
       18    16.5
       19    17.5
    Name: B, Length: 20, dtype: float64

    The expanding() method will accumulate a given operation (sum() in the example) for all the members of each particular group.

    expanding() 메서드는 각 특정 그룹의 모든 구성원에 대해 지정된 작업(예제에서는 sum())을 누적한다.

    df_re.groupby("A").expanding().sum()
    Out[171]:
              B
    A
    1 0     0.0
      1     1.0
      2     3.0
      3     6.0
      4    10.0
    ...     ...
    5 15   75.0
      16   91.0
      17  108.0
      18  126.0
      19  145.0
    
    [20 rows x 1 columns]

    Suppose you want to use the resample() method to get a daily frequency in each group of your dataframe, and wish to complete the missing values with the ffill() method.

    resample() 메서드를 사용하여 데이터프레임의 각 그룹에서 일일 빈도를 얻고 ffill() 메서드로 누락된 값을 완성한다고 가정해 본다.

    df_re = pd.DataFrame(
        {
            "date": pd.date_range(start="2016-01-01", periods=4, freq="W"),
            "group": [1, 1, 2, 2],
            "val": [5, 6, 7, 8],
        }
    ).set_index("date")
    
    
    df_re
    Out[173]:
                group  val
    date
    2016-01-03      1    5
    2016-01-10      1    6
    2016-01-17      2    7
    2016-01-24      2    8
    
    df_re.groupby("group").resample("1D", include_groups=False).ffill()
    Out[174]:
                      val
    group date
    1     2016-01-03    5
          2016-01-04    5
          2016-01-05    5
          2016-01-06    5
          2016-01-07    5
    ...               ...
    2     2016-01-20    7
          2016-01-21    7
          2016-01-22    7
          2016-01-23    7
          2016-01-24    8
    
    [16 rows x 1 columns]

    Filtration

    A filtration is a GroupBy operation that subsets the original grouping object. It may either filter out entire groups, part of groups, or both. Filtrations return a filtered version of the calling object, including the grouping columns when provided. In the following example, class is included in the result.

    필터링은 원래 그룹화 개체의 하위 집합을 지정하는 GroupBy 작업이다. 전체 그룹, 그룹의 일부 또는 둘 다를 필터링할 수 있다. 필터링은 제공된 경우 그룹화 열을 포함하여 호출 개체의 필터링된 버전을 반환한다. 다음 예에서는 클래스가 결과에 포함된다.

    speeds
    Out[175]:
              class           order  max_speed
    falcon     bird   Falconiformes      389.0
    parrot     bird  Psittaciformes       24.0
    lion     mammal       Carnivora       80.2
    monkey   mammal        Primates        NaN
    leopard  mammal       Carnivora       58.0
    
    speeds.groupby("class").nth(1)
    Out[176]:
             class           order  max_speed
    parrot    bird  Psittaciformes       24.0
    monkey  mammal        Primates        NaN

    Note

    Unlike aggregations, filtrations do not add the group keys to the index of the result. Because of this, passing as_index=False or sort=True will not affect these methods.

    집계와 달리 필터링은 결과 인덱스에 그룹 키를 추가하지 않는다. 따라서 as_index=False 또는 sort=True를 전달해도 이러한 메서드에는 영향을 미치지 않는다.

    Filtrations will respect subsetting the columns of the GroupBy object.

    필터링은 GroupBy 개체의 열 하위 집합을 따른다.

    speeds.groupby("class")[["order", "max_speed"]].nth(1)
    Out[177]:
                     order  max_speed
    parrot  Psittaciformes       24.0
    monkey        Primates        NaN

    Built-in filtrations

    The following methods on GroupBy act as filtrations. All these methods have an efficient, GroupBy-specific, implementation.

    GroupBy의 다음 메서드는 필터링 역할을 한다. 이러한 모든 메서드에는 효율적인 GroupBy별 구현이 있다.

    Method Description
    head() Select the top row(s) of each group
    nth() Select the nth row(s) of each group
    tail() Select the bottom row(s) of each group
    방법 설명
    head() 각 그룹의 맨 위 행을 선택한다.
    nth() 각 그룹의 n번째 행을 선택한다.
    tail() 각 그룹의 맨 아래 행을 선택한다.

    Users can also use transformations along with Boolean indexing to construct complex filtrations within groups. For example, suppose we are given groups of products and their volumes, and we wish to subset the data to only the largest products capturing no more than 90% of the total volume within each group.

    사용자는 부울 인덱싱과 함께 변환을 사용하여 그룹 내에서 복잡한 필터링을 구성할 수도 있다. 예를 들어, 제품 그룹과 해당 볼륨이 주어지고 각 그룹 내 총 볼륨의 90% 이하를 캡처하는 가장 큰 제품으로만 데이터의 하위 집합을 만들고 싶다고 가정한다.

    product_volumes = pd.DataFrame(
        {
            "group": list("xxxxyyy"),
            "product": list("abcdefg"),
            "volume": [10, 30, 20, 15, 40, 10, 20],
        }
    )
    
    
    product_volumes
    Out[179]:
      group product  volume
    0     x       a      10
    1     x       b      30
    2     x       c      20
    3     x       d      15
    4     y       e      40
    5     y       f      10
    6     y       g      20
    
    # Sort by volume to select the largest products first
    
    product_volumes = product_volumes.sort_values("volume", ascending=False)
    
    grouped = product_volumes.groupby("group")["volume"]
    
    cumpct = grouped.cumsum() / grouped.transform("sum")
    
    cumpct
    Out[183]:
    4    0.571429
    1    0.400000
    2    0.666667
    6    0.857143
    3    0.866667
    0    1.000000
    5    1.000000
    Name: volume, dtype: float64
    
    significant_products = product_volumes[cumpct <= 0.9]
    
    significant_products.sort_values(["group", "product"])
    Out[185]:
      group product  volume
    1     x       b      30
    2     x       c      20
    3     x       d      15
    4     y       e      40
    6     y       g      20

    The filter method

    Note

    Filtering by supplying filter with a User-Defined Function (UDF) is often less performant than using the built-in methods on GroupBy. Consider breaking up a complex operation into a chain of operations that utilize the built-in methods.

    UDF(사용자 정의 함수)로 필터를 제공하여 필터링하는 것은 GroupBy에 내장된 메서드를 사용하는 것보다 성능이 떨어지는 경우가 많다. 복잡한 작업을 기본 제공 메서드를 활용하는 작업 체인으로 나누는 것을 고려해보자.

    The filter method takes a User-Defined Function (UDF) that, when applied to an entire group, returns either True or False. The result of the filter method is then the subset of groups for which the UDF returned True.

    Suppose we want to take only elements that belong to groups with a group sum greater than 2.

    필터 메소드는 전체 그룹에 적용될 때 True 또는 False를 반환하는 사용자 정의 함수(UDF)를 사용한다. 필터 메소드의 결과는 UDF가 True를 반환한 그룹의 하위 집합이다.

    그룹 합이 2보다 큰 그룹에 속한 요소만 가져오고 싶다고 가정해 본다.

    sf = pd.Series([1, 1, 2, 3, 3, 3])
    
    sf.groupby(sf).filter(lambda x: x.sum() > 2)
    Out[187]:
    3    3
    4    3
    5    3
    dtype: int64

    Another useful operation is filtering out elements that belong to groups with only a couple members.

    또 다른 유용한 작업은 몇 명의 구성원만 있는 그룹에 속한 요소를 필터링하는 것이다.

    dff = pd.DataFrame({"A": np.arange(8), "B": list("aabbbbcc")})
    
    dff.groupby("B").filter(lambda x: len(x) > 2)
    Out[189]:
       A  B
    2  2  b
    3  3  b
    4  4  b
    5  5  b

    Alternatively, instead of dropping the offending groups, we can return a like-indexed objects where the groups that do not pass the filter are filled with NaNs.

    또는 문제가 있는 그룹을 삭제하는 대신 필터를 통과하지 못한 그룹이 NaN으로 채워지는 유사 인덱스 객체를 반환할 수 있다.

    dff.groupby("B").filter(lambda x: len(x) > 2, dropna=False)
    Out[190]:
         A    B
    0  NaN  NaN
    1  NaN  NaN
    2  2.0    b
    3  3.0    b
    4  4.0    b
    5  5.0    b
    6  NaN  NaN
    7  NaN  NaN

    For DataFrames with multiple columns, filters should explicitly specify a column as the filter criterion.

    여러 열이 있는 DataFrame의 경우 필터는 열을 필터 기준으로 명시적으로 지정해야 한다.

    dff["C"] = np.arange(8)
    
    dff.groupby("B").filter(lambda x: len(x["C"]) > 2)
    Out[192]:
       A  B  C
    2  2  b  2
    3  3  b  3
    4  4  b  4
    5  5  b  5

    Flexible apply / 유연한 적용

    Some operations on the grouped data might not fit into the aggregation, transformation, or filtration categories. For these, you can use the apply function.

    그룹화된 데이터에 대한 일부 작업은 집계, 변환 또는 필터링 범주에 맞지 않을 수 있다. 이를 위해 apply 함수를 사용할 수 있다.

    Warning

    apply has to try to infer from the result whether it should act as a reducer, transformer, or filter, depending on exactly what is passed to it. Thus the grouped column(s) may be included in the output or not. While it tries to intelligently guess how to behave, it can sometimes guess wrong.

    apply는 전달된 내용에 따라 결과에서 reducer, transformer 또는 filter로 작동해야 하는지 추론해야 한다. 따라서 그룹화된 열이 출력에 포함될 수도 있고 포함되지 않을 수도 있다. 어떻게 행동해야 할지 지능적으로 추측하려고 시도하지만 때로는 잘못된 추측을 할 수도 있다.

    Note

    All of the examples in this section can be more reliably, and more efficiently, computed using other pandas functionality.

    이 섹션의 모든 예제는 다른 Pandas 기능을 사용하여 더 안정적이고 효율적으로 계산할 수 있다.

    df
    Out[193]:
         A      B         C         D
    0  foo    one -0.575247  1.346061
    1  bar    one  0.254161  1.511763
    2  foo    two -1.143704  1.627081
    3  bar  three  0.215897 -0.990582
    4  foo    two  1.193555 -0.441652
    5  bar    two -0.077118  1.211526
    6  foo    one -0.408530  0.268520
    7  foo  three -0.862495  0.024580
    
    grouped = df.groupby("A")
    
    # could also just call .describe()
    grouped["C"].apply(lambda x: x.describe())
    Out[195]:
    A
    bar  count    3.000000
         mean     0.130980
         std      0.181231
         min     -0.077118
         25%      0.069390
                    ...
    foo  min     -1.143704
         25%     -0.862495
         50%     -0.575247
         75%     -0.408530
         max      1.193555
    Name: C, Length: 16, dtype: float64

    The dimension of the returned result can also change:

    반환된 결과의 차원도 변경될 수 있다.

    grouped = df.groupby('A')['C']
    
    def f(group):
        return pd.DataFrame({'original': group,
                             'demeaned': group - group.mean()})
    
    
    grouped.apply(f)
    Out[198]:
           original  demeaned
    A
    bar 1  0.254161  0.123181
        3  0.215897  0.084917
        5 -0.077118 -0.208098
    foo 0 -0.575247 -0.215962
        2 -1.143704 -0.784420
        4  1.193555  1.552839
        6 -0.408530 -0.049245
        7 -0.862495 -0.503211

    apply on a Series can operate on a returned value from the applied function that is itself a series, and possibly upcast the result to a DataFrame:

    시리즈에 대한 적용은 그 자체가 시리즈인 적용된 함수에서 반환된 값에 대해 작업을 수행할 수 있으며 결과를 DataFrame으로 업캐스트할 수도 있다.

    def f(x):
        return pd.Series([x, x ** 2], index=["x", "x^2"])
    
    
    s = pd.Series(np.random.rand(5))
    
    s
    Out[201]:
    0    0.582898
    1    0.098352
    2    0.001438
    3    0.009420
    4    0.815826
    dtype: float64
    
    s.apply(f)
    Out[202]:
              x       x^2
    0  0.582898  0.339770
    1  0.098352  0.009673
    2  0.001438  0.000002
    3  0.009420  0.000089
    4  0.815826  0.665572

    Similar to The aggregate() method, the resulting dtype will reflect that of the apply function. If the results from different groups have different dtypes, then a common dtype will be determined in the same way as DataFrame construction.

    aggregate() 메서드와 유사하게 결과 dtype은 적용 함수의 dtype을 반영한다. 서로 다른 그룹의 결과에 서로 다른 dtype이 있는 경우 DataFrame 구성과 동일한 방식으로 공통 dtype이 결정된다.

    Control grouped column(s) placement with group_keys / group_keys를 사용하여 그룹화된 열 배치 제어

    To control whether the grouped column(s) are included in the indices, you can use the argument group_keys which defaults to True. Compare

    그룹화된 열이 인덱스에 포함되는지 여부를 제어하려면 기본값이 True인 group_keys 인수를 사용할 수 있다. 비교해보라.

    df.groupby("A", group_keys=True).apply(lambda x: x, include_groups=False)
    Out[203]:
               B         C         D
    A
    bar 1    one  0.254161  1.511763
        3  three  0.215897 -0.990582
        5    two -0.077118  1.211526
    foo 0    one -0.575247  1.346061
        2    two -1.143704  1.627081
        4    two  1.193555 -0.441652
        6    one -0.408530  0.268520
        7  three -0.862495  0.024580

    with

    df.groupby("A", group_keys=False).apply(lambda x: x, include_groups=False)
    Out[204]:
           B         C         D
    0    one -0.575247  1.346061
    1    one  0.254161  1.511763
    2    two -1.143704  1.627081
    3  three  0.215897 -0.990582
    4    two  1.193555 -0.441652
    5    two -0.077118  1.211526
    6    one -0.408530  0.268520
    7  three -0.862495  0.024580

     

    Numba Accelerated Routines / Numba 가속 루틴

    New in version 1.1.

    If Numba is installed as an optional dependency, the transform and aggregate methods support engine='numba' and engine_kwargs arguments. See enhancing performance with Numba for general usage of the arguments and performance considerations.

    The function signature must start with values, index exactly as the data belonging to each group will be passed into values, and the group index will be passed into index.

    버전 1.1의 새로운 기능이다.

    Numba가 선택적 종속성으로 설치된 경우 변환 및 집계 메소드는 engine='numba' 및 engine_kwargs 인수를 지원한다. 인수의 일반적인 사용법과 성능 고려 사항은 Numba를 통한 성능 향상을 참조하라.

    함수 시그니처는 값으로 시작해야 하며, 각 그룹에 속한 데이터가 값으로 전달되는 것과 정확히 일치하는 인덱스를 갖고, 그룹 인덱스가 인덱스로 전달된다.

    Warning

    When using engine='numba', there will be no “fall back” behavior internally. The group data and group index will be passed as NumPy arrays to the JITed user defined function, and no alternative execution attempts will be tried.

    engine='numba'를 사용하면 내부적으로 "대체" 동작이 없다. 그룹 데이터 및 그룹 인덱스는 JITed 사용자 정의 함수에 NumPy 배열로 전달되며 대체 실행 시도는 시도되지 않는다.

    Other useful features / 기타 유용한 기능

    Exclusion of non-numeric columns / 숫자가 아닌 열 제외

    Again consider the example DataFrame we’ve been looking at:

    우리가 살펴본 DataFrame 예제를 다시 생각해 보자.

    df
    Out[205]:
         A      B         C         D
    0  foo    one -0.575247  1.346061
    1  bar    one  0.254161  1.511763
    2  foo    two -1.143704  1.627081
    3  bar  three  0.215897 -0.990582
    4  foo    two  1.193555 -0.441652
    5  bar    two -0.077118  1.211526
    6  foo    one -0.408530  0.268520
    7  foo  three -0.862495  0.024580

    Suppose we wish to compute the standard deviation grouped by the A column. There is a slight problem, namely that we don’t care about the data in column B because it is not numeric. You can avoid non-numeric columns by specifying numeric_only=True:

    A 열로 그룹화된 표준 편차를 계산한다고 가정한다. 약간의 문제가 있다. 즉, B 열의 데이터는 숫자가 아니기 때문에 신경 쓰지 않는다는 것이다. numeric_only=True를 지정하면 숫자가 아닌 열을 피할 수 있다.

    df.groupby("A").std(numeric_only=True)
    Out[206]:
                C         D
    A
    bar  0.181231  1.366330
    foo  0.912265  0.884785

    Note that df.groupby('A').colname.std(). is more efficient than df.groupby('A').std().colname. So if the result of an aggregation function is only needed over one column (here colname), it may be filtered before applying the aggregation function.

    df.groupby('A').colname.std()에 유의하라. df.groupby('A').std().colname보다 더 효율적이다. 따라서 집계 함수의 결과가 하나의 열(여기서는 colname)에 대해서만 필요한 경우 집계 함수를 적용하기 전에 필터링될 수 있다.

    from decimal import Decimal
    
    df_dec = pd.DataFrame(
        {
            "id": [1, 2, 1, 2],
            "int_column": [1, 2, 3, 4],
            "dec_column": [
                Decimal("0.50"),
                Decimal("0.15"),
                Decimal("0.25"),
                Decimal("0.40"),
            ],
        }
    )
    
    
    df_dec.groupby(["id"])[["dec_column"]].sum()
    Out[209]:
       dec_column
    id
    1        0.75
    2        0.55

    Handling of (un)observed Categorical values / 관찰되지 않은(비)범주형 값 처리

    When using a Categorical grouper (as a single grouper, or as part of multiple groupers), the observed keyword controls whether to return a cartesian product of all possible groupers values (observed=False) or only those that are observed groupers (observed=True).

    범주형 그룹화를 사용하는 경우(단일 그룹화 또는 여러 그룹화의 일부로) 관찰 키워드는 가능한 모든 그룹화 값(observed=False)의 데카르트 곱을 반환할지 아니면 관찰된 그룹화 값(observed=True)만 반환할지를 제어한다.

    Show all values:

    모든 값 표시:

    pd.Series([1, 1, 1]).groupby(
        pd.Categorical(["a", "a", "a"], categories=["a", "b"]), observed=False
    ).count()
    
    Out[210]:
    a    3
    b    0
    dtype: int64

    Show only the observed values:

    관찰된 값만 표시:

    pd.Series([1, 1, 1]).groupby(
        pd.Categorical(["a", "a", "a"], categories=["a", "b"]), observed=True
    ).count()
    
    Out[211]:
    a    3
    dtype: int64

    The returned dtype of the grouped will always include all of the categories that were grouped.

    그룹화된 항목의 반환된 dtype에는 항상 그룹화된 모든 범주가 ​​포함된다.

    s = (
        pd.Series([1, 1, 1])
        .groupby(pd.Categorical(["a", "a", "a"], categories=["a", "b"]), observed=True)
        .count()
    )
    
    
    s.index.dtype
    Out[213]: CategoricalDtype(categories=['a', 'b'], ordered=False, categories_dtype=object)

    NA group handling

    By NA, we are referring to any NA values, including NA, NaN, NaT, and None. If there are any NA values in the grouping key, by default these will be excluded. In other words, any “NA group” will be dropped. You can include NA groups by specifying dropna=False.

    NA는 NA, NaN, NaT 및 None을 포함한 모든 NA 값을 나타낸다. 그룹화 키에 NA 값이 있으면 기본적으로 제외된다. 즉, "NA 그룹"이 삭제된다. dropna=False를 지정하여 NA 그룹을 포함할 수 있다.

    df = pd.DataFrame({"key": [1.0, 1.0, np.nan, 2.0, np.nan], "A": [1, 2, 3, 4, 5]})
    
    df
    Out[215]:
       key  A
    0  1.0  1
    1  1.0  2
    2  NaN  3
    3  2.0  4
    4  NaN  5
    
    df.groupby("key", dropna=True).sum()
    Out[216]:
         A
    key
    1.0  3
    2.0  4
    
    df.groupby("key", dropna=False).sum()
    Out[217]:
         A
    key
    1.0  3
    2.0  4
    NaN  8

    Grouping with ordered factors / 순서화된 팩터로 그룹화

    Categorical variables represented as instances of pandas’s Categorical class can be used as group keys. If so, the order of the levels will be preserved. When observed=False and sort=False, any unobserved categories will be at the end of the result in order.

    Pandas의 Categorical 클래스의 인스턴스로 표현되는 범주형 변수를 그룹 키로 사용할 수 있다. 만일 그렇다면 레벨의 순서가 유지된다. observed=False 및 sort=False인 경우 관찰되지 않은 범주는 순서대로 결과 끝에 표시된다.

    days = pd.Categorical(
        values=["Wed", "Mon", "Thu", "Mon", "Wed", "Sat"],
        categories=["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
    )
    
    
    data = pd.DataFrame(
       {
           "day": days,
           "workers": [3, 4, 1, 4, 2, 2],
       }
    )
    
    
    data
    Out[220]:
       day  workers
    0  Wed        3
    1  Mon        4
    2  Thu        1
    3  Mon        4
    4  Wed        2
    5  Sat        2
    
    data.groupby("day", observed=False, sort=True).sum()
    Out[221]:
         workers
    day
    Mon        8
    Tue        0
    Wed        5
    Thu        1
    Fri        0
    Sat        2
    Sun        0
    
    data.groupby("day", observed=False, sort=False).sum()
    Out[222]:
         workers
    day
    Wed        5
    Mon        8
    Thu        1
    Sat        2
    Tue        0
    Fri        0
    Sun        0

    Grouping with a grouper specification

    You may need to specify a bit more data to properly group. You can use the pd.Grouper to provide this local control.

    적절하게 그룹화하려면 데이터를 조금 더 지정해야 할 수도 있다. pd.Grouper를 사용하여 이 로컬 제어를 제공할 수 있다.

    import datetime
    
    df = pd.DataFrame(
        {
            "Branch": "A A A A A A A B".split(),
            "Buyer": "Carl Mark Carl Carl Joe Joe Joe Carl".split(),
            "Quantity": [1, 3, 5, 1, 8, 1, 9, 3],
            "Date": [
                datetime.datetime(2013, 1, 1, 13, 0),
                datetime.datetime(2013, 1, 1, 13, 5),
                datetime.datetime(2013, 10, 1, 20, 0),
                datetime.datetime(2013, 10, 2, 10, 0),
                datetime.datetime(2013, 10, 1, 20, 0),
                datetime.datetime(2013, 10, 2, 10, 0),
                datetime.datetime(2013, 12, 2, 12, 0),
                datetime.datetime(2013, 12, 2, 14, 0),
            ],
        }
    )
    
    
    df
    Out[225]:
      Branch Buyer  Quantity                Date
    0      A  Carl         1 2013-01-01 13:00:00
    1      A  Mark         3 2013-01-01 13:05:00
    2      A  Carl         5 2013-10-01 20:00:00
    3      A  Carl         1 2013-10-02 10:00:00
    4      A   Joe         8 2013-10-01 20:00:00
    5      A   Joe         1 2013-10-02 10:00:00
    6      A   Joe         9 2013-12-02 12:00:00
    7      B  Carl         3 2013-12-02 14:00:00

    Groupby a specific column with the desired frequency. This is like resampling.

    원하는 빈도로 특정 열을 그룹화한다. 이는 리샘플링과 같다.

    df.groupby([pd.Grouper(freq="1ME", key="Date"), "Buyer"])[["Quantity"]].sum()
    Out[226]:
                      Quantity
    Date       Buyer
    2013-01-31 Carl          1
               Mark          3
    2013-10-31 Carl          6
               Joe           9
    2013-12-31 Carl          3
               Joe           9

    When freq is specified, the object returned by pd.Grouper will be an instance of pandas.api.typing.TimeGrouper. When there is a column and index with the same name, you can use key to group by the column and level to group by the index.

    freq가 지정되면 pd.Grouper가 반환하는 개체는 pandas.api.typing.TimeGrouper의 인스턴스가 된다. 동일한 이름의 컬럼과 인덱스가 있는 경우 키를 사용하여 컬럼별로 그룹화하고 레벨을 사용하여 인덱스별로 그룹화할 수 있다.

    df = df.set_index("Date")
    
    df["Date"] = df.index + pd.offsets.MonthEnd(2)
    
    df.groupby([pd.Grouper(freq="6ME", key="Date"), "Buyer"])[["Quantity"]].sum()
    Out[229]:
                      Quantity
    Date       Buyer
    2013-02-28 Carl          1
               Mark          3
    2014-02-28 Carl          9
               Joe          18
    
    df.groupby([pd.Grouper(freq="6ME", level="Date"), "Buyer"])[["Quantity"]].sum()
    Out[230]:
                      Quantity
    Date       Buyer
    2013-01-31 Carl          1
               Mark          3
    2014-01-31 Carl          9
               Joe          18

    Taking the first rows of each group / 각 그룹의 첫 번째 행 가져오기

    Just like for a DataFrame or Series you can call head and tail on a groupby:

    DataFrame이나 Series와 마찬가지로 groupby에서 head와 tail을 호출할 수 있다.

    df = pd.DataFrame([[1, 2], [1, 4], [5, 6]], columns=["A", "B"])
    
    df
    Out[232]:
       A  B
    0  1  2
    1  1  4
    2  5  6
    
    g = df.groupby("A")
    
    g.head(1)
    Out[234]:
       A  B
    0  1  2
    2  5  6
    
    g.tail(1)
    Out[235]:
       A  B
    1  1  4
    2  5  6

    This shows the first or last n rows from each group.

    각 그룹의 첫 번째 또는 마지막 n개 행이 표시된다.

    Taking the nth row of each group / 각 그룹의 n번째 행을 가져오기

    To select the nth item from each group, use DataFrameGroupBy.nth() or SeriesGroupBy.nth(). Arguments supplied can be any integer, lists of integers, slices, or lists of slices; see below for examples. When the nth element of a group does not exist an error is not raised; instead no corresponding rows are returned.

    In general this operation acts as a filtration. In certain cases it will also return one row per group, making it also a reduction. However because in general it can return zero or multiple rows per group, pandas treats it as a filtration in all cases.

    각 그룹에서 n번째 항목을 선택하려면 DataFrameGroupBy.nth() 또는 SeriesGroupBy.nth()를 사용한다. 제공된 인수는 정수, 정수 리스트, 슬라이스 또는 슬라이스 리스트일 수 있다. 예시는 아래를 참조하라. 그룹의 n번째 요소가 존재하지 않으면 오류가 발생하지 않는다. 대신 해당 행이 반환되지 않는다.

    일반적으로 이 작업은 필터링 역할을 한다. 어떤 경우에는 그룹당 하나의 행을 반환하여 감소하기도 한다. 그러나 일반적으로 그룹당 0개 또는 여러 개의 행을 반환할 수 있으므로 pandas는 모든 경우에 이를 필터링으로 처리한다.

    df = pd.DataFrame([[1, np.nan], [1, 4], [5, 6]], columns=["A", "B"])
    
    g = df.groupby("A")
    
    g.nth(0)
    Out[238]:
       A    B
    0  1  NaN
    2  5  6.0
    
    g.nth(-1)
    Out[239]:
       A    B
    1  1  4.0
    2  5  6.0
    
    g.nth(1)
    Out[240]:
       A    B
    1  1  4.0

    If the nth element of a group does not exist, then no corresponding row is included in the result. In particular, if the specified n is larger than any group, the result will be an empty DataFrame.

    그룹의 n번째 요소가 존재하지 않으면 해당 행이 결과에 포함되지 않는다. 특히, 지정된 n이 어떤 그룹보다 크면 결과는 빈 DataFrame이 된다.

    g.nth(5)
    Out[241]:
    Empty DataFrame
    Columns: [A, B]
    Index: []

    If you want to select the nth not-null item, use the dropna kwarg. For a DataFrame this should be either 'any' or 'all' just like you would pass to dropna:

    null이 아닌 n번째 항목을 선택하려면 dropna kwarg를 사용하라. DataFrame의 경우 dropna에 전달하는 것처럼 'any' 또는 'all'이어야 한다.

    # nth(0) is the same as g.first()
    g.nth(0, dropna="any")
    Out[242]:
       A    B
    1  1  4.0
    2  5  6.0
    
    g.first()
    Out[243]:
         B
    A
    1  4.0
    5  6.0
    
    # nth(-1) is the same as g.last()
    g.nth(-1, dropna="any")
    Out[244]:
       A    B
    1  1  4.0
    2  5  6.0
    
    g.last()
    Out[245]:
         B
    A
    1  4.0
    5  6.0
    
    g.B.nth(0, dropna="all")
    Out[246]:
    1    4.0
    2    6.0
    Name: B, dtype: float64

    You can also select multiple rows from each group by specifying multiple nth values as a list of ints.

    여러 n번째 값을 정수 리스트으로 지정하여 각 그룹에서 여러 행을 선택할 수도 있다.

    business_dates = pd.date_range(start="4/1/2014", end="6/30/2014", freq="B")
    
    df = pd.DataFrame(1, index=business_dates, columns=["a", "b"])
    
    # get the first, 4th, and last date index for each month
    df.groupby([df.index.year, df.index.month]).nth([0, 3, -1])
    Out[249]:
                a  b
    2014-04-01  1  1
    2014-04-04  1  1
    2014-04-30  1  1
    2014-05-01  1  1
    2014-05-06  1  1
    2014-05-30  1  1
    2014-06-02  1  1
    2014-06-05  1  1
    2014-06-30  1  1

    You may also use slices or lists of slices.

    슬라이스 또는 슬라이스 리스트을 사용할 수도 있다.

    df.groupby([df.index.year, df.index.month]).nth[1:]
    Out[250]:
                a  b
    2014-04-02  1  1
    2014-04-03  1  1
    2014-04-04  1  1
    2014-04-07  1  1
    2014-04-08  1  1
    ...        .. ..
    2014-06-24  1  1
    2014-06-25  1  1
    2014-06-26  1  1
    2014-06-27  1  1
    2014-06-30  1  1
    
    [62 rows x 2 columns]
    
    df.groupby([df.index.year, df.index.month]).nth[1:, :-1]
    Out[251]:
                a  b
    2014-04-01  1  1
    2014-04-02  1  1
    2014-04-03  1  1
    2014-04-04  1  1
    2014-04-07  1  1
    ...        .. ..
    2014-06-24  1  1
    2014-06-25  1  1
    2014-06-26  1  1
    2014-06-27  1  1
    2014-06-30  1  1
    
    [65 rows x 2 columns]

    Enumerate group items

    To see the order in which each row appears within its group, use the cumcount method:

    그룹 내에서 각 행이 나타나는 순서를 보려면 cumcount 메소드를 사용하라.

    dfg = pd.DataFrame(list("aaabba"), columns=["A"])
    
    dfg
    Out[253]:
       A
    0  a
    1  a
    2  a
    3  b
    4  b
    5  a
    
    dfg.groupby("A").cumcount()
    Out[254]:
    0    0
    1    1
    2    2
    3    0
    4    1
    5    3
    dtype: int64
    
    dfg.groupby("A").cumcount(ascending=False)
    Out[255]:
    0    3
    1    2
    2    1
    3    1
    4    0
    5    0
    dtype: int64

    Enumerate groups

    To see the ordering of the groups (as opposed to the order of rows within a group given by cumcount) you can use DataFrameGroupBy.ngroup().

    Note that the numbers given to the groups match the order in which the groups would be seen when iterating over the groupby object, not the order they are first observed.

    그룹 순서를 보려면(cumcount로 지정된 그룹 내 행 순서와 반대) DataFrameGroupBy.ngroup()을 사용할 수 있다.

    그룹에 주어진 숫자는 그룹이 처음 관찰된 순서가 아니라 groupby 객체를 반복할 때 그룹이 표시되는 순서와 일치한다.

    dfg = pd.DataFrame(list("aaabba"), columns=["A"])
    
    dfg
    Out[257]:
       A
    0  a
    1  a
    2  a
    3  b
    4  b
    5  a
    
    dfg.groupby("A").ngroup()
    Out[258]:
    0    0
    1    0
    2    0
    3    1
    4    1
    5    0
    dtype: int64
    
    dfg.groupby("A").ngroup(ascending=False)
    Out[259]:
    0    1
    1    1
    2    1
    3    0
    4    0
    5    1
    dtype: int64

    Plotting

    Groupby also works with some plotting methods. In this case, suppose we suspect that the values in column 1 are 3 times higher on average in group “B”.

    Groupby는 일부 플로팅 메서드와도 작동한다. 이 경우 열 1의 값이 그룹 "B"에서 평균 3배 더 높다고 의심한다고 가정해 본다.

    np.random.seed(1234)
    
    df = pd.DataFrame(np.random.randn(50, 2))
    
    df["g"] = np.random.choice(["A", "B"], size=50)
    
    df.loc[df["g"] == "B", 1] += 3

    We can easily visualize this with a boxplot:

    상자 그림을 사용하여 이를 쉽게 시각화할 수 있다.

    df.groupby("g").boxplot()
    Out[264]:
    A         Axes(0.1,0.15;0.363636x0.75)
    B    Axes(0.536364,0.15;0.363636x0.75)
    dtype: object

    https://pandas.pydata.org/pandas-docs/stable/_images/groupby_boxplot.png

    The result of calling boxplot is a dictionary whose keys are the values of our grouping column g (“A” and “B”). The values of the resulting dictionary can be controlled by the return_type keyword of boxplot. See the visualization documentation for more.

    boxplot을 호출한 결과는 키가 그룹화 열 g("A" 및 "B")의 값인 딕셔너리이다. 결과 딕셔너리의 값은 boxplot의 return_type 키워드로 제어할 수 있다. 자세한 내용은 시각화 문서를 참조하라.

    Warning

    For historical reasons, df.groupby("g").boxplot() is not equivalent to df.boxplot(by="g"). See here for an explanation.

    역사적인 이유로 df.groupby("g").boxplot()은 df.boxplot(by="g")와 동일하지 않다. 설명은 여기를 참조하라.

    Piping function calls

    Similar to the functionality provided by DataFrame and Series, functions that take GroupBy objects can be chained together using a pipe method to allow for a cleaner, more readable syntax. To read about .pipe in general terms, see here.

    Combining .groupby and .pipe is often useful when you need to reuse GroupBy objects.

    As an example, imagine having a DataFrame with columns for stores, products, revenue and quantity sold. We’d like to do a groupwise calculation of prices (i.e. revenue/quantity) per store and per product. We could do this in a multi-step operation, but expressing it in terms of piping can make the code more readable. First we set the data:

    DataFrame 및 Series에서 제공하는 기능과 유사하게 GroupBy 개체를 사용하는 함수는 pipe 메서드를 사용하여 함께 연결되어 더 깔끔하고 읽기 쉬운 구문을 허용할 수 있다. .pipe에 대한 일반적인 용어를 읽으려면 여기를 참조하라.

    GroupBy 개체를 재사용해야 할 때 .groupby와 .pipe를 결합하는 것이 유용한 경우가 많다.

    예를 들어 매장, 제품, 매출, 판매 수량에 대한 열이 있는 DataFrame이 있다고 가정해 보자. 매장별, 제품별 가격(예: 수익/수량)을 그룹별로 계산하고 싶을 때 이를 다단계 작업으로 수행할 수 있지만 이를 파이핑 측면에서 표현하면 코드를 더 읽기 쉽게 만들 수 있다. 먼저 데이터를 설정한다.

    n = 1000
    
    df = pd.DataFrame(
        {
            "Store": np.random.choice(["Store_1", "Store_2"], n),
            "Product": np.random.choice(["Product_1", "Product_2"], n),
            "Revenue": (np.random.random(n) * 50 + 10).round(2),
            "Quantity": np.random.randint(1, 10, size=n),
        }
    )
    
    
    df.head(2)
    Out[267]:
         Store    Product  Revenue  Quantity
    0  Store_2  Product_1    26.12         1
    1  Store_2  Product_1    28.86         1

    We now find the prices per store/product.

    이제 매장/제품별 가격을 확인할 수 있다.

    (
        df.groupby(["Store", "Product"])
        .pipe(lambda grp: grp.Revenue.sum() / grp.Quantity.sum())
        .unstack()
        .round(2)
    )
    
    Out[268]:
    Product  Product_1  Product_2
    Store
    Store_1       6.82       7.05
    Store_2       6.30       6.64

    Piping can also be expressive when you want to deliver a grouped object to some arbitrary function, for example:

    파이프는 그룹화된 개체를 임의의 기능에 전달하려는 경우에도 표현할 수 있다. 예를 들면 다음과 같다.

    def mean(groupby):
        return groupby.mean()
    
    
    df.groupby(["Store", "Product"]).pipe(mean)
    Out[270]:
                         Revenue  Quantity
    Store   Product
    Store_1 Product_1  34.622727  5.075758
            Product_2  35.482815  5.029630
    Store_2 Product_1  32.972837  5.237589
            Product_2  34.684360  5.224000

    Here mean takes a GroupBy object and finds the mean of the Revenue and Quantity columns respectively for each Store-Product combination. The mean function can be any function that takes in a GroupBy object; the .pipe will pass the GroupBy object as a parameter into the function you specify.

    여기서 평균은 GroupBy 개체를 사용하여 각 상점-제품 조합에 대해 각각 Revenue 및 Quantity 열의 평균을 찾는다. 평균 함수는 GroupBy 개체를 사용하는 모든 함수일 수 있다. .pipe는 GroupBy 개체를 사용자가 지정하는 함수에 매개 변수로 전달한다.

    Examples

    Multi-column factorization / 다중 열 분해

    By using DataFrameGroupBy.ngroup(), we can extract information about the groups in a way similar to factorize() (as described further in the reshaping API) but which applies naturally to multiple columns of mixed type and different sources. This can be useful as an intermediate categorical-like step in processing, when the relationships between the group rows are more important than their content, or as input to an algorithm which only accepts the integer encoding. (For more information about support in pandas for full categorical data, see the Categorical introduction and the API documentation.)

    DataFrameGroupBy.ngroup()을 사용하면 (reshaping API에서 자세히 설명된 대로) factorize()와 유사한 방식으로 그룹에 대한 정보를 추출할 수 있지만 이는 혼합 유형과 다양한 소스의 여러 열에 자연스럽게 적용된다. 이는 그룹 행 간의 관계가 내용보다 더 중요한 경우 처리에서 범주형 중간 단계로 유용할 수 있으며, 정수 인코딩만 허용하는 알고리즘에 대한 입력으로 유용할 수 있다. (전체 범주형 데이터에 대한 Pandas 지원에 대한 자세한 내용은 범주형 소개 및 [API 설명서](https://pandas.pydata.org/pandas-docs/stable/reference/arrays.html#api-arrays-categorical)를 참조하라.)

    dfg = pd.DataFrame({"A": [1, 1, 2, 3, 2], "B": list("aaaba")})
    
    dfg
    Out[272]:
       A  B
    0  1  a
    1  1  a
    2  2  a
    3  3  b
    4  2  a
    
    dfg.groupby(["A", "B"]).ngroup()
    Out[273]:
    0    0
    1    0
    2    1
    3    2
    4    1
    dtype: int64
    
    dfg.groupby(["A", [0, 0, 0, 1, 1]]).ngroup()
    Out[274]:
    0    0
    1    0
    2    1
    3    3
    4    2
    dtype: int64

    Groupby by indexer to ‘resample’ data / 데이터 '리샘플링'을 위한 indexer별 Groupby

    Resampling produces new hypothetical samples (resamples) from already existing observed data or from a model that generates data. These new samples are similar to the pre-existing samples.

    In order for resample to work on indices that are non-datetimelike, the following procedure can be utilized.

    In the following examples, df.index // 5 returns an integer array which is used to determine what gets selected for the groupby operation.

    리샘플링은 이미 존재하는 관측 데이터 또는 데이터를 생성하는 모델로부터 새로운 가상 샘플(리샘플)을 생성한다. 이 새로운 샘플은 기존 샘플과 유사하다.

    날짜/시간이 아닌 인덱스에서 재샘플을 수행하려면 다음 절차를 활용할 수 있다.

    다음 예에서 df.index // 5는 groupby 작업을 위해 선택되는 항목을 결정하는 데 사용되는 정수 배열을 반환한다.

    Note

    The example below shows how we can downsample by consolidation of samples into fewer ones. Here by using df.index // 5, we are aggregating the samples in bins. By applying std() function, we aggregate the information contained in many samples into a small subset of values which is their standard deviation thereby reducing the number of samples.

    아래 예에서는 샘플을 더 적은 수의 샘플로 통합하여 다운샘플링하는 방법을 보여준다. 여기에서는 df.index // 5를 사용하여 샘플을 bin에 집계한다. std() 함수를 적용하여 많은 샘플에 포함된 정보를 표준 편차인 값의 작은 하위 집합으로 집계하여 샘플 수를 줄인다.

    df = pd.DataFrame(np.random.randn(10, 2))
    
    df
    Out[276]:
              0         1
    0 -0.793893  0.321153
    1  0.342250  1.618906
    2 -0.975807  1.918201
    3 -0.810847 -1.405919
    4 -1.977759  0.461659
    5  0.730057 -1.316938
    6 -0.751328  0.528290
    7 -0.257759 -1.081009
    8  0.505895 -1.701948
    9 -1.006349  0.020208
    
    df.index // 5
    Out[277]: Index([0, 0, 0, 0, 0, 1, 1, 1, 1, 1], dtype='int64')
    
    df.groupby(df.index // 5).std()
    Out[278]:
              0         1
    0  0.823647  1.312912
    1  0.760109  0.942941

    Returning a Series to propagate names / 이름을 전파하기 위해 시리즈 반환하기

    Group DataFrame columns, compute a set of metrics and return a named Series. The Series name is used as the name for the column index. This is especially useful in conjunction with reshaping operations such as stacking, in which the column index name will be used as the name of the inserted column:

    DataFrame 열을 그룹화하고 일련의 측정항목을 계산하고 명명된 시리즈를 반환한다. 시리즈 이름은 열 인덱스의 이름으로 사용된다. 이는 열 인덱스 이름이 삽입된 열의 이름으로 사용되는 스택과 같은 재형성 작업과 함께 특히 유용하다.

    df = pd.DataFrame(
        {
            "a": [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2],
            "b": [0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1],
            "c": [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0],
            "d": [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1],
        }
    )
    
    
    def compute_metrics(x):
        result = {"b_sum": x["b"].sum(), "c_mean": x["c"].mean()}
        return pd.Series(result, name="metrics")
    
    
    result = df.groupby("a").apply(compute_metrics, include_groups=False)
    
    result
    Out[282]:
    metrics  b_sum  c_mean
    a
    0          2.0     0.5
    1          2.0     0.5
    2          2.0     0.5
    
    result.stack(future_stack=True)
    Out[283]:
    a  metrics
    0  b_sum      2.0
       c_mean     0.5
    1  b_sum      2.0
       c_mean     0.5
    2  b_sum      2.0
       c_mean     0.5
    dtype: float64
    728x90

    댓글

Designed by Tistory.