programing

().sum()에 의해 판다 그룹의 출력에서 새 열을 만들려면 어떻게 해야 합니까?

powerit 2023. 7. 22. 10:31
반응형

().sum()에 의해 판다 그룹의 출력에서 새 열을 만들려면 어떻게 해야 합니까?

에새 에서 새 .groupbyㅠㅠ 그룹 ), 새로운 (으)ㄹ 수 있습니다.df['Data4']와 함께 NaN을 그래서 나는 데이터 프레임에 다음의 합계를 사용하여 새 열을 만들려고 합니다.Data3모든 날짜에 대해 각 날짜 행에 적용합니다.예를 들어, 2015-05-08은 2개 행(합계 50+5 = 55)에 있으며, 이 새 열에는 두 행 모두 55개가 있습니다.

import pandas as pd

df = pd.DataFrame({
    'Date' : ['2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05', '2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05'], 
    'Sym'  : ['aapl', 'aapl', 'aapl', 'aapl', 'aaww', 'aaww', 'aaww', 'aaww'], 
    'Data2': [11, 8, 10, 15, 110, 60, 100, 40],
    'Data3': [5, 8, 6, 1, 50, 100, 60, 120]
})

group = df['Data3'].groupby(df['Date']).sum()

df['Data4'] = group

group:

Date
2015-05-05    121
2015-05-06     66
2015-05-07    108
2015-05-08     55
Name: Data3, dtype: int64

df마지막에:

         Date   Sym  Data2  Data3  Data4
0  2015-05-08  aapl     11      5    NaN
1  2015-05-07  aapl      8      8    NaN
2  2015-05-06  aapl     10      6    NaN
3  2015-05-05  aapl     15      1    NaN
4  2015-05-08  aaww    110     50    NaN
5  2015-05-07  aaww     60    100    NaN
6  2015-05-06  aaww    100     60    NaN
7  2015-05-05  aaww     40    120    NaN

당신은 사용하길 원합니다.그러면 인덱스가 df에 정렬된 Series(영상 시리즈)가 반환되므로 새 열로 추가할 수 있습니다.

df = pd.DataFrame({
    'Date': ['2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05',
             '2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05'],
    'Sym': ['aapl', 'aapl', 'aapl', 'aapl', 'aaww', 'aaww', 'aaww', 'aaww'],
    'Data2': [11, 8, 10, 15, 110, 60, 100, 40],
    'Data3': [5, 8, 6, 1, 50, 100, 60, 120]
})
​
df['Data4'] = df['Data3'].groupby(df['Date']).transform('sum')
df
         Date   Sym  Data2  Data3  Data4
0  2015-05-08  aapl     11      5     55
1  2015-05-07  aapl      8      8    108
2  2015-05-06  aapl     10      6     66
3  2015-05-05  aapl     15      1    121
4  2015-05-08  aaww    110     50     55
5  2015-05-07  aaww     60    100    108
6  2015-05-06  aaww    100     60     66
7  2015-05-05  aaww     40    120    121

().sum()에 의해 판다 그룹의 출력에서 새 열을 만들려면 어떻게 해야 합니까?

두 가지 방법이 있습니다. 하나는 직접적이고 다른 하나는 조금 더 흥미롭습니다.


모든 사용자가 가장 좋아하는 것:GroupBy.transform()와 함께'sum'

@EdChum의 대답은 조금 더 단순화될 수 있습니다.불러DataFrame.groupbySeries.groupby따라서 구문이 단순해집니다.

df.groupby('Date')['Data3'].transform('sum')

0     55
1    108
2     66
3    121
4     55
5    108
6     66
7    121
Name: Data3, dtype: int64 

좀 더 빠르긴 하지만,

df2 = pd.concat([df] * 12345)

%timeit df2['Data3'].groupby(df['Date']).transform('sum')
%timeit df2.groupby('Date')['Data3'].transform('sum')

10.4 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
8.58 ms ± 559 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

할 가치가 .GroupBy.sum()+Series.map()

저는 API에서 흥미로운 특이점을 우연히 발견했습니다.제가 알기로는 0.20 이상의 메이저 버전에서도 이를 재현할 수 있습니다(0.23과 0.24에서 테스트했습니다).몇 밀리초의 시간을 지속적으로 줄일 수 있는 것 같습니다.transform에 대신직접기사경우용는하능의 한다면,GroupBy그리고 그것을 사용하여 방송합니다.map:

df['Date'].map(df.groupby('Date')['Data3'].sum())

0     55
1    108
2     66
3    121
4     55
5    108
6     66
7    121
Name: Date, dtype: int64

.df.groupby('Date')['Data3'].transform('sum')그들은 똑같습니다.

내 테스트에 따르면map직접 사용할 수 있는 여유가 있다면 조금 더 빠릅니다.GroupBy: 능예기(예):mean,min,max,first등). 대부분의 일반적인 상황에서 약 20만 개의 레코드까지 속도가 다소 빠릅니다.그 이후에는 데이터에 따라 성능이 크게 좌우됩니다.

(왼쪽: v0.23, 오른쪽: v0.24)

이것은 알 수 있는 좋은 대안이며, 그룹 수가 적은 작은 프레임이 더 좋지만, 저는 추천합니다.transform했습니다.어쨌든 이것을 공유할 가치가 있다고 생각했습니다.

참조용 벤치마킹 코드:

import perfplot

perfplot.show(
    setup=lambda n: pd.DataFrame({'A': np.random.choice(n//10, n), 'B': np.ones(n)}),
    kernels=[
        lambda df: df.groupby('A')['B'].transform('sum'),
        lambda df:  df.A.map(df.groupby('A')['B'].sum()),
    ],
    labels=['GroupBy.transform', 'GroupBy.sum + map'],
    n_range=[2**k for k in range(5, 20)],
    xlabel='N',
    logy=True,
    logx=True
)

값이 그룹에 대한 작업으로 정의되고 동일한 그룹 내에서 다른 값을 가질 수 있는 새 열을 정의하는 것과 같이 더 복잡한 용도에서도 단일 식으로 쿼리를 작성할 수 있는 보다 강력한 것을 일반적으로 사용할 것을 제안합니다!

은 모든더입니다(예: 이는모든그룹예대해동열가니다더일단입경적반순다우보한정는의하을진값을일한 에예▁this▁with:(▁column다니▁the▁(like▁of일입▁a더▁is▁defining▁more반적▁for▁than:sum이 질문에서는 그룹별로 다른 값이 동일한 그룹 내에서 동일합니다.

단순 대소문자(그룹 내에서 동일한 값을 가진 새 열, 그룹 간에 다름):

# I'm assuming the name of your dataframe is something long, like
# `my_data_frame`, to show the power of being able to write your
# data processing in a single expression without multiple statements and
# multiple references to your long name, which is the normal style
# that the pandas API naturally makes you adopt, but which make the
# code often verbose, sparse, and a pain to generalize or refactor

my_data_frame = pd.DataFrame({
    'Date': ['2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05', '2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05'], 
    'Sym': ['aapl', 'aapl', 'aapl', 'aapl', 'aaww', 'aaww', 'aaww', 'aaww'], 
    'Data2': [11, 8, 10, 15, 110, 60, 100, 40],
    'Data3': [5, 8, 6, 1, 50, 100, 60, 120]})
​
(my_data_frame
    # create groups by 'Date'
    .groupby(['Date'])
    # for every small Group DataFrame `gdf` with the same 'Date', do:
    # assign a new column 'Data4' to it, with the value being
    # the sum of 'Data3' for the small dataframe `gdf`
    .apply(lambda gdf: gdf.assign(Data4=lambda gdf: gdf['Data3'].sum()))
    # after groupby operations, the variable(s) you grouped by on
    # are set as indices. In this case, 'Date' was set as an additional
    # level for the (multi)index. But it is still also present as a
    # column. Thus, we drop it from the index:
    .droplevel(0)
)

### OR

# We don't even need to define a variable for our dataframe.
# We can chain everything in one expression

(pd
    .DataFrame({
        'Date': ['2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05', '2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05'], 
        'Sym': ['aapl', 'aapl', 'aapl', 'aapl', 'aaww', 'aaww', 'aaww', 'aaww'], 
        'Data2': [11, 8, 10, 15, 110, 60, 100, 40],
        'Data3': [5, 8, 6, 1, 50, 100, 60, 120]})
    .groupby(['Date'])
    .apply(lambda gdf: gdf.assign(Data4=lambda gdf: gdf['Data3'].sum()))
    .droplevel(0)
)

외부:

날짜. 데이터2 데이터 3 데이터 4
3 2015-05-05 사과 한 알 15 1 121
7 2015-05-05 으스스한 사람 40 120 121
2 2015-05-06 사과 한 알 10 6 66
6 2015-05-06 으스스한 사람 100 60 66
1 2015-05-07 사과 한 알 8 8 108
5 2015-05-07 으스스한 사람 60 100 108
0 2015-05-08 사과 한 알 11 5 55
4 2015-05-08 으스스한 사람 110 50 55

(왜 python 표현식이 괄호 안에 있습니까?코드에 백슬래시를 뿌릴 필요가 없고 표현 코드 내에 주석을 달아 모든 단계를 설명할 수 있습니다.)

이것의 강력한 점은 무엇입니까?그것은 "분할-적용-결합 패러다임"의 모든 힘을 활용하고 있다는 것입니다.이를 통해 행 수를 줄이지 않고도 데이터 프레임을 블록으로 분할하고 "블록에서 임의 작업을 실행"하는 것을 고려할 수 있습니다. (또한 명시적이고 자세한 루프를 작성하지 않고 값비싼 조인 또는 연결을 사용하여 결과를 다시 결합할 수 있습니다.)

좀 더 복잡한 예를 살펴보겠습니다.데이터 프레임에 여러 개의 시계열 데이터가 있는 데이터입니다.제품 종류를 나타내는 열, 타임스탬프가 있는 열 및 해당 제품에 대해 연중 특정 시점에 판매된 품목 수가 들어 있는 열이 있습니다.제품별로 그룹화하여 각 범주에 대해 판매된 품목의 누적 합계가 들어 있는 새 열을 얻으려고 합니다.동일한 제품을 사용하는 모든 "블록" 내에서 여전히 시계열이며 단조롭게 증가하는(블록 내에서만) 열을 원합니다.

어떻게 하면 좋을까요?와 함께groupby+apply!

(pd
     .DataFrame({
        'Date': ['2021-03-11','2021-03-12','2021-03-13','2021-03-11','2021-03-12','2021-03-13'], 
        'Product': ['shirt','shirt','shirt','shoes','shoes','shoes'], 
        'ItemsSold': [300, 400, 234, 80, 10, 120],
        })
    .groupby(['Product'])
    .apply(lambda gdf: (gdf
        # sort by date within a group
        .sort_values('Date')
        # create new column
        .assign(CumulativeItemsSold=lambda df: df['ItemsSold'].cumsum())))
    .droplevel(0)
)

외부:

날짜. 제품. 판매된 아이템 누적 판매 품목 수
0 2021-03-11 셔츠 300 300
1 2021-03-12 셔츠 400 700
2 2021-03-13 셔츠 234 934
3 2021-03-11 신발. 80 80
4 2021-03-12 신발. 10 90
5 2021-03-13 신발. 120 210

이 방법의 또 다른 장점은?여러 개의 필드로 그룹화해야 하는 경우에도 효과가 있습니다!를 들어,에, 리만약예를▁a가 있으면,'Color'우리 제품의 필드, 그리고 우리는 누적 시리즈를 그룹화하기를 원했습니다.(Product, Color)할 수 있는 일:

(pd
     .DataFrame({
        'Date': ['2021-03-11','2021-03-12','2021-03-13','2021-03-11','2021-03-12','2021-03-13',
                 '2021-03-11','2021-03-12','2021-03-13','2021-03-11','2021-03-12','2021-03-13'], 
        'Product': ['shirt','shirt','shirt','shoes','shoes','shoes',
                    'shirt','shirt','shirt','shoes','shoes','shoes'], 
        'Color': ['yellow','yellow','yellow','yellow','yellow','yellow',
                  'blue','blue','blue','blue','blue','blue'], # new!
        'ItemsSold': [300, 400, 234, 80, 10, 120,
                      123, 84, 923, 0, 220, 94],
        })
    .groupby(['Product', 'Color']) # We group by 2 fields now
    .apply(lambda gdf: (gdf
        .sort_values('Date')
        .assign(CumulativeItemsSold=lambda df: df['ItemsSold'].cumsum())))
    .droplevel([0,1]) # We drop 2 levels now

외부:

날짜. 제품. 색. 판매된 아이템 누적 판매 품목 수
6 2021-03-11 셔츠 파랑색 123 123
7 2021-03-12 셔츠 파랑색 84 207
8 2021-03-13 셔츠 파랑색 923 1130
0 2021-03-11 셔츠 노란 색 300 300
1 2021-03-12 셔츠 노란 색 400 700
2 2021-03-13 셔츠 노란 색 234 934
9 2021-03-11 신발. 파랑색 0 0
10 2021-03-12 신발. 파랑색 220 220
11 2021-03-13 신발. 파랑색 94 314
3 2021-03-11 신발. 노란 색 80 80
4 2021-03-12 신발. 노란 색 10 90
5 2021-03-13 신발. 노란 색 120 210

(여러 필드에 걸쳐 그룹화로 쉽게 확장할 수 있는 이러한 가능성이 제가 다음과 같은 주장을 제기하는 이유입니다.groupby이전 예제의 '제품'과 같이 단일 이름이라도 항상 목록에 표시됩니다.)

그리고 이 모든 것을 하나의 표현으로 합성할 수 있습니다. (물론, 파이썬의 람다가 조금 더 보기 좋다면, 훨씬 더 멋져 보일 것입니다.


왜 내가 일반적인 사건을 검토했을까요?이 질문은 "pand as new column groupby"와 같은 항목을 검색할 때 나타나는 첫 번째 SO 질문 중 하나이기 때문입니다.


이런 종류의 작업을 위한 API에 대한 추가적인 생각

그룹에 대한 임의 계산을 기반으로 열을 추가하는 것은 SparkSQL에서 Windows를 통해 집계를 사용하여 새 열을 정의하는 좋은 관용어입니다.

예를 들어 다음과 같이 생각할 수 있습니다(Scala 코드이지만 PySpark의 동일한 코드는 실질적으로 동일합니다).

val byDepName = Window.partitionBy('depName)
empsalary.withColumn("avg", avg('salary) over byDepName)

(위에서 본 방식으로 판다를 사용하는 것)과 같은 것으로.

empsalary = pd.DataFrame(...some dataframe...)
(empsalary
    # our `Window.partitionBy('depName)`
    .groupby(['depName'])
    # our 'withColumn("avg", avg('salary) over byDepName)
    .apply(lambda gdf: gdf.assign(avg=lambda df: df['salary'].mean()))
    .droplevel(0)
)

(Spark 예제가 얼마나 합성적이고 더 좋은지 주목하십시오.동등한 판다들은 약간 투박해 보입니다.Pandas API는 이러한 종류의 "유연한" 작업을 작성하는 것을 쉽게 만들지 않습니다.

이 관용구는 차례로 Postgre가 사용하는 SQL의 Window Functions에서 유래되었습니다.SQL 설명서는 다음에 대한 매우 좋은 정의를 제공합니다(내 것 강조).

창 함수는 현재 행과 관련된 테이블집합에 걸쳐 계산을 수행합니다.이는 집계 함수로 수행할 수 있는 계산 유형과 유사합니다.그러나 일반 집계 함수와 달리 창 함수를 사용하면 행이 단일 출력 행으로 그룹화되지 않고 행이 개별 ID를 유지합니다.백그라운드에서 창 기능은 쿼리 결과의 현재 행 이상에 액세스할 수 있습니다.

그리고 아름다운 SQL 한 줄 예제를 제공합니다. (그룹 내 순위 지정)

SELECT depname, empno, salary, rank() OVER (PARTITION BY depname ORDER BY salary DESC) FROM empsalary;
명예를 더럽히다 엠프노 급여 순위
발전시키다 8 6000 1
발전시키다 10 5200 2
발전시키다 11 5200 2
발전시키다 9 4500 4
발전시키다 7 4200 5
인사들 2 3900 1
인사들 5 3500 2
판매의 1 5000 1
판매의 4 4800 2
판매의 3 4800 2

마지막으로: 여러분은 또한 판다에 관심이 있을지도 모릅니다, 그것은 유사합니다.apply하지만 조금 다르게 작동하고 내부 운영에 더 큰 범위를 제공합니다.자세한 내용은 여기를 참조하십시오.

df = pd.DataFrame({
'Date' : ['2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05', '2015-05-08', '2015-05-07', '2015-05-06', '2015-05-05'], 
'Sym'  : ['aapl', 'aapl', 'aapl', 'aapl', 'aaww', 'aaww', 'aaww', 'aaww'], 
'Data2': [11, 8, 10, 15, 110, 60, 100, 40],
'Data3': [5, 8, 6, 1, 50, 100, 60, 120]
})
print(pd.pivot_table(data=df,index='Date',columns='Sym',     aggfunc={'Data2':'sum','Data3':'sum'}))

산출량

Data2      Data3     
Sym         aapl aaww  aapl aaww
Date                            
2015-05-05    15   40     1  120
2015-05-06    10  100     6   60
2015-05-07     8   60     8  100
2015-05-08    11  110     5   50

언급URL : https://stackoverflow.com/questions/30244952/how-do-i-create-a-new-column-from-the-output-of-pandas-groupby-sum

반응형