<jupyter_start><jupyter_text>11 그룹연산판다스의 그룹 연산은 데이터를 집계하거나 변환하는 등의 작업을 한 번에 처리할 수 있는 강력한 기능입니다. 보통 그룹 연산은 데이터를 '분할'하고 '반영'하고 '결합'하는 과정을 거치게 되는데, '분할'은 어떤 기준으로 데이터를 나누는 것이고 '반영'은 함수 등을 적용하여 데이터를 처리하는 것입니다. 그리고 '결합'은 처리한 결과를 다시 합치는 것이죠. 보통 이 과정을 하나로 묶어 '분할-반영-결합(Split-Apply-Combine)이라고 합니다. 혹시 데이터베이스를 공부한 적이 있나요? 그러면 판다스의 groupby 메서드가 SQL의 GROUP BY 구문과 비슷하다는 것을 알 수 있을 것입니다. 사실 '분할-반영-결합'은 오래 전부터 분산 컴퓨팅 분야에서 빅데이터(Big Data)를 처리하기 위해 사용했던 방법입니다. 물론 그룹 연산을 사용하지 않아도 개별적인 과정으로 데이터를 분할, 반영, 결합할 수 있습니다. 하지만 그룹 연산을 사용하면 더 큰 용량의 데이터도 손쉽게 처리할 수 있기 때문에 반드시 알아두어야 합니다. 11-1 데이터 집계 11-2 데이터 변환 11-3 데이터 필터링 11-4 그룹 오브젝트  11 - 1 데이터 집계 데이터 집게하기 - groupby 메서드02장에서 갭마인더 데이터 집합으로 각 연도의 평균 수명을 구했던 것을 기억하나요? 수집한 데이터를 바탕으로 평균이나 합 등을 구하여 의미 있는 값을 도출해 내는 것을 '집계'라고 합니다. 데이터를 집계하면 전체 데이터를 요약, 정리하여 볼 수 있기 때문에 데이터 분석이 훨씬 편해지죠. 그러면 groupby 메서드로 평균값을 구하는 과정을 통해 데이터 집계가 무엇인지 알아보겠습니다. groupby 메서드로 평균값 구하기 1. 먼저 갭마인더 데이터 집합을 불러옵니다.<jupyter_code>import pandas as pd
df = pd.read_csv('./data/gapminder.tsv', sep='\t')<jupyter_output><empty_output><jupyter_text>2.다음은 yrar 열을 기준으로 데이터를 그룹화한 다음 lifeExp 열의 평균을 구한 것입니다.<jupyter_code>avg_life_exp_by_year = df.groupby('year').lifeExp.mean()
print(avg_life_exp_by_year)<jupyter_output>year
1952    49.057620
1957    51.507401
1962    53.609249
1967    55.678290
1972    57.647386
1977    59.570157
1982    61.533197
1987    63.212613
1992    64.160338
1997    65.014676
2002    65.694923
2007    67.007423
Name: lifeExp, dtype: float64<jupyter_text>븐할 - 반영 -결합 과정 살펴보기 - groupby 메서드앞으로 groupby 메서드를 사용해 lifeExp 열의 연도별 평균값을 구했습니다. 그러면 실제로 groupby 메서드는 어떤 과정을 통해 데이터를 집계할까요? groupby 메서드를 자체를 분해하여 살펴보는 것은 불가능하기 때문에 비슷한 연산을 수행하는 메서드를 순서대로 실행하며 알아보겠습니다. 분할-반영-결합 과정 살펴보기 1.실제로 groupby 메서드에 life 열을 전달하면 가장 먼저 연도별로 데이터를 나누는 과정이 진행됩니다. 다음은 year 열의 데이터를 중복 없이 추출한 것입니다. groupby 메서드에 열이름을 전달하면 이런 '분할' 작업이 먼저 일어난다고 이해하세요.<jupyter_code>years = df.year.unique()
print(years)<jupyter_output>[1952 1957 1962 1967 1972 1977 1982 1987 1992 1997 2002 2007]<jupyter_text>2.그런 다음에는 연도별로 평균값을 구합니다. 그러려면 일단 각 연도별로 데이터를 추출해야겠죠? 다음은 1952년의 데이터를 추출한 것입니다. 이 과정을 '반영' 작업의 한 부분이라고 이해하세요.<jupyter_code>y1952 = df.loc[df.year == 1952, :]
print(y1952.head())<jupyter_output>country continent  year  lifeExp       pop    gdpPercap
0   Afghanistan      Asia  1952   28.801   8425333   779.445314
12      Albania    Europe  1952   55.230   1282697  1601.056136
24      Algeria    Africa  1952   43.077   9279525  2449.008185
36       Angola    Africa  1952   30.015   4232095  3520.610273
48    Argentina  Americas  1952   62.485  17876956  5911.315053<jupyter_text>3.아직 lifeExp 열의 평균값을 구하지 않았습니다. 다음은 과정2에서 추출한 1952년의 데이터에서 lifeExp 열의 평균값을 구한 것입니다. 이 과정도'반영' 작업의 한 부분입니다.<jupyter_code>y1952_mean = y1952.lifeExp.mean()
print(y1952_mean)<jupyter_output>49.057619718309866<jupyter_text>4. 과정 2~3을 반복하여 남은 연도의 평균값을 구하면 비소로 '반영' 작업이 끝납니다.<jupyter_code>y1957 = df.loc[df.year == 1957, :]
y1957_mean = y1957.lifeExp.mean()
print(y1957_mean)

y1962 = df.loc[df.year == 1962, :] 
y1962_mean = y1962.lifeExp.mean( )
print(y1962_mean)

y2007 = df.loc[df.year == 2007, :] 
y2007_mean = y2007.lifeExp.mean( )
print(y2007_mean)<jupyter_output>51.50740112676056
53.609249014084504
67.00742253521126<jupyter_text>5.마지막으로 연도별로 계산하 lifeExp의 평균값을 합칩니다. 바로 이 과정이 '결합' 작업입니다.<jupyter_code>df2 = pd.DataFrame({"year":[1952, 1957, 1962, 2007], 
                   "":[y1952_mean, y1957_mean, y1962_mean, y2007_mean]})
print(df2)<jupyter_output>year           
0  1952  49.057620
1  1957  51.507401
2  1962  53.609249
3  2007  67.007423<jupyter_text>groupby 메서드와 함께 사용하는 집계 메서드다음은 집계 메서드를 정리한 표입니다. 이후에 수행할 실습에서 자주등장하는 메서드이니 미리 읽어보고 넘어가는 것이 좋습니다.  집계 메서드- count : 누락값을 제외한 데이터 수를 변환- size  : 누락값을 포함한 데이터 수를 반환- mean : 평균값 반환- std : 표준편차 반환- min : 최솟값 반환- quantile(q=0.25) :백분위수 25%- quantile(q=0.50) : 백분위수 50%- quantile(q=0.75) : 백분위수 75%- max : 최댓값 반환- sum : 전체 합 반환- var : 분산 반환- sem : 평균의 표준편차 반환- describe : 데이터 수, 평균, 표준편차, 최소값, 백분위수(25,50,75%), 최댓값을 모두 반환- first : 첫 번째 행 반환- last : 마지막 행 반환- nth : n 번째 행 반환  agg 메서드로 사용자 함수와 groupby 메서드 조합하기라이브러리에서 제공하는 집계 메서드로 원하는 값을 계산할 수 없는 경우에는 직접 함수를 만들어서 사용해야 합니다. 이번에는 사용자 함수와 groupby 메서드를 조합해서 사용해 보겠습니다. 사용자 함수와 groupby 메서드를 조합하려면 agg 메서드를 이용해야 합니다.  평균값을 구하는 사용자 함수와 groupby 메서드 1.다음은 입력바은 열의 평균값을 구하는 함수입니다.<jupyter_code>def my_mean(values):
    n = len(values)
    sum = 0
    for value in values:
        sum += value
        
        return sum / n<jupyter_output><empty_output><jupyter_text>2.다음은 과정 1에서 만든 함수를 groupby 메서드와 조합하기 위해 agg 메서드를 사용한 것입니다. 결과를 보면 mean 메서드를 사용하여 얻은 값과 동일하다는 것을 알 수 있습니다.<jupyter_code>agg_my_mean = df.groupby('year').lifeExp.agg(my_mean)
print(agg_my_mean)<jupyter_output>year
1952    0.202824
1957    0.213606
1962    0.225331
1967    0.239577
1972    0.254141
1977    0.270690
1982    0.280662
1987    0.287479
1992    0.293479
1997    0.294106
2002    0.296683
2007    0.308648
Name: lifeExp, dtype: float64<jupyter_text>2개의 인잣값을 받아 처리하는 사용자 함수 groupby 메서드 1. 이번에는 2개의 인잣값을 받아 처리하는 사용자 정의 함수(my_mean_diff)를 만들어 보겠습니다. 다음은 첫 번째 인자로 받은 열의 평균값을 구하여 두 번째 인자로 받은 값과의 차이를 계산한 다음 반환하는 함수입니다.<jupyter_code>def my_mean_diff(values, diff_value):
    n = len(values)
    sum = 0
    for value in values:
        sum += value
        mean = sum / n
        return mean - diff_value<jupyter_output><empty_output><jupyter_text>2.다음은 연도별 평균 수명에서 전체 평균 수명을 뺀 값을 구한 것입니다. agg 메서드의 첫 번째 인자에 my_mean_diff 함수를 전달하고 두 번째 인자에 전체 평균 수명값을 전달 했습니다.<jupyter_code>global_mean = df.lifeExp.mean()
print(global_mean)
agg_mean_diff = df.groupby('year').lifeExp.agg(my_mean_diff, diff_value = global_mean)
print(agg_mean_diff)<jupyter_output>year
1952   -59.271615
1957   -59.260834
1962   -59.249108
1967   -59.234862
1972   -59.220299
1977   -59.203749
1982   -59.193777
1987   -59.186960
1992   -59.180960
1997   -59.180334
2002   -59.177756
2007   -59.165791
Name: lifeExp, dtype: float64<jupyter_text>여러 개의 집계 메서드 한 번에 사용하기여러 개의 집계 메서드를 한 번에 사용하고 싶다면 어떻게 해야 할까요? 집계 메서드를 리스트나 딕셔너리에 담아 agg 메서드에 전달하면 됩니다.  집계 메서드를 리스트, 딕셔너리에 담아 전달하기 1.다음은 연도별로 그룹화한 lifeExp 열의 0이 아닌 값의 개수, 평균 표준편차를 한 번에 계산하여 출력한 것입니다. 넘파이 메서드인 count_nonzero, mean, std를 리스트에 담아 agg 메서드에 전달했습니다.<jupyter_code>import numpy as np
gdf = df.groupby('year').lifeExp.agg([np.count_nonzero, np.mean, np.std])
print(gdf)<jupyter_output>count_nonzero       mean        std
year                                     
1952          142.0  49.057620  12.225956
1957          142.0  51.507401  12.231286
1962          142.0  53.609249  12.097245
1967          142.0  55.678290  11.718858
1972          142.0  57.647386  11.381953
1977          142.0  59.570157  11.227229
1982          142.0  61.533197  10.770618
1987          142.0  63.212613  10.556285
1992          142.0  64.160338  11.227380
1997          142.0  65.014676  11.559439
2002          142.0  65.694923  12.279823
2007          142.0  67.007423  12.073021<jupyter_text>2.이번에는 집계 메서드를 딕셔너리에 담아 agg 메서드에 전달해 보겠습니다. 딕셔너리의 키로 집계 메서드를 적용할 열 이름을 전달하고 딕셔너리의 값으로 집계 메서드를 전달 하면됩니다.<jupyter_code>gdf_dict = df.groupby('year').agg({'lifeExp':'mean', 'pop':'median', 'gdpPercap':'median'})
print(gdf_dict)<jupyter_output>lifeExp         pop    gdpPercap
year                                    
1952  49.057620   3943953.0  1968.528344
1957  51.507401   4282942.0  2173.220291
1962  53.609249   4686039.5  2335.439533
1967  55.678290   5170175.5  2678.334741
1972  57.647386   5877996.5  3339.129407
1977  59.570157   6404036.5  3798.609244
1982  61.533197   7007320.0  4216.228428
1987  63.212613   7774861.5  4280.300366
1992  64.160338   8688686.5  4386.085502
1997  65.014676   9735063.5  4781.825478
2002  65.694923  10372918.5  5319.804524
2007  67.007423  10517531.0  6124.371109<jupyter_text>11-2 데이터 변환11-1 에서는 집계 메서드의 활용법을 알아보았습니다. 이번에는 데이터 변환 메서드에 대해 알아보겠습니다. 데이터 변환 메서드는 데이터와 메서드를 일대일로 대응시켜 계산하기 때문에 데이터의 양이 줄어들지 않습니다. 말 그대로 데이터를 변환하는 데 사용합니다. 표준점수 계산하기통계 분야에서는 데이터의 평균과 표준편차의 차이를 표준점수라고 부릅니다. 표준점수를 구하면 변환한 데이터의 평균값이 0이 되고 표준편차는 1이 됩니다. 그러면 데이터가 표준화되어 서로 다른 데이터를 쉽게 비교할 수 있게 되죠. 표준점수는 통계에서 자주 사용하는 지표입니다. 표준점수 계산하기 1.다음은 표준점수를 계산하는 함수입니다.<jupyter_code>def my_zscore(x):
    return(x - x.mean()) / x.std()<jupyter_output><empty_output><jupyter_text>2.다음은 각 연도별 lifeExp 열의 표준점수를 계산한 것입니다. my_zscore 함수를 적용하기 위해 transform 메서드를 사용했습니다.<jupyter_code>transform_z = df.groupby('year').lifeExp.transform(my_zscore)
print(transform_z.head())<jupyter_output>0   -1.656854
1   -1.731249
2   -1.786543
3   -1.848157
4   -1.894173
Name: lifeExp, dtype: float64<jupyter_text>3.my_zscore 함수는 데이터를 표준화할 뿐 집계는 하지 않습니다. 즉, 데이터의 양이 줄어들지 않습니다. 다음은 원본 데이터프레임(df)의 데이터 크기와 변환한 데이터프레임(transform_z)의 데이터 크기를 비교한 것입니다.<jupyter_code>print(df.shape)
print(transform_z.shape)<jupyter_output>(1704,)<jupyter_text>누락값을 평균값으로 처리하기06장에서 누락값을 처리하는 다양한 방법에 대해 살펴봤습니다. 하지만 가끔은 누락값을 평균값으로 처리하는 것이 더 좋을 때가 있습니다. 이번에는 누락값을 평균값으로 처리하는 방법을 알아보겠습니다. 누락값을 평균값으로 처리하기 1.다음은 seaborn 라이브러리 tips 데이터 집합에서 10개의 행 데이터만 가져온 다음 total_bill 열의 값 4개를 임의로 선택하여 누락값으로 바꾼 것입니다.<jupyter_code>import seaborn as sns
import numpy as np

np.random.seed(42)
tips_10 = sns.load_dataset('tips').sample(10)
tips_10.loc[np.random.permutation(tips_10.index)[:4], 'total_bill'] = np.NaN
print(tips_10)<jupyter_output>total_bill   tip     sex smoker   day    time  size
24        19.82  3.18    Male     No   Sat  Dinner     2
6          8.77  2.00    Male     No   Sun  Dinner     2
153         NaN  2.00    Male     No   Sun  Dinner     4
211         NaN  5.16    Male    Yes   Sat  Dinner     4
198         NaN  2.00  Female    Yes  Thur   Lunch     2
176         NaN  2.00    Male    Yes   Sun  Dinner     2
192       28.44  2.56    Male    Yes  Thur   Lunch     2
124       12.48  2.52  Female     No  Thur   Lunch     2
9         14.78  3.23    Male     No   Sun  Dinner     2
101       15.38  3.00  Female    Yes   Fri  Dinner     2<jupyter_text>2.그런데 total_bill 열의 누락값을 단순히 total_bill 열의 평균값으로 채우면 안 됩니다. 무슨 말일까요? 현재 tips_10의 데이터는 여성보다 남성이 더 많습니다. 즉, 여성과 남성을 구분하여 total_bill 열의 평균값을 구하지 않으면 여성 데이터가 남성 데이터의 영향을 많이 받아 여성의 데이터가 훼손될 수 있습니다. 다음은 성별로 그룹화한 다음 각 열의 데이터 수를 구한 것입니다. total_bill 열을 살펴보면 남성의 누락값은 3개, 여성의 누락값은 1개라는 것을 알 수 있습니다.<jupyter_code>count_sex = tips_10.groupby('sex').count()
print(count_sex)<jupyter_output>total_bill  tip  smoker  day  time  size
sex                                             
Male             4    7       7    7     7     7
Female           2    3       3    3     3     3<jupyter_text>3.다음은 성별을 구분하여 total_bill 열의 데이터를 받아 평균값을 구하는 함수입니다.<jupyter_code>def fill_na_mean(x):
    avg = x.mean()
    return x.fillna(avg)<jupyter_output><empty_output><jupyter_text>4.다음은 성별을 구분한 total_bill 열의 데이터를 fill_na_mean함수에 전달하여 평균값을 구한 다음 tips_10에 새로운 열로 추가한 것입니다. 남성과 여성의 누락값을 고려하여 계산한 평균값으로 잘 채워져 있는 것을 알 수 있습니다.<jupyter_code>total_bill_group_mean = tips_10.groupby('sex').total_bill.transform(fill_na_mean)
tips_10['fill_total_bill'] = total_bill_group_mean
print(tips_10)<jupyter_output>total_bill   tip     sex smoker   day    time  size  fill_total_bill
24        19.82  3.18    Male     No   Sat  Dinner     2          19.8200
6          8.77  2.00    Male     No   Sun  Dinner     2           8.7700
153         NaN  2.00    Male     No   Sun  Dinner     4          17.9525
211         NaN  5.16    Male    Yes   Sat  Dinner     4          17.9525
198         NaN  2.00  Female    Yes  Thur   Lunch     2          13.9300
176         NaN  2.00    Male    Yes   Sun  Dinner     2          17.9525
192       28.44  2.56    Male    Yes  Thur   Lunch     2          28.4400
124       12.48  2.52  Female     No  Thur   Lunch     2          12.4800
9         14.78  3.23    Male     No   Sun  Dinner     2          14.7800
101       15.38  3.00  Female    Yes   Fri  Dinner     2          15.3800<jupyter_text>11 - 3 데이터 필터링만약 그룹화한 데이터에서 원하는 데이터를 걸러내고 싶다면 어떻게 해야 할까요? 그럴 때는 데이터 필터링을 사용하면 됩니다. 데이터 필터링을 사용하면 기준에 맞는 데이터를 걸러낼 수 있습니다. 다음 예제를 통해 데이터 필터링이 무엇인지 알아보겠습니다.  데이터 필터링 사용하기 -filter 메서드 1.다음과 같이 tips 데이터 집합을 불러와 데이터 크기를 확인합니다.<jupyter_code>tips = sns.load_dataset('tips')
print(tips.shape)<jupyter_output>(244, 7)<jupyter_text>2.size 열의 데이터 수를 확인해 보면 1,5,6 테이블의 주문이 매우 적다는 것을 알 수 있습니다.<jupyter_code>print(tips['size'].value_counts())<jupyter_output>2    156
3     38
4     37
5      5
6      4
1      4
Name: size, dtype: int64<jupyter_text>3.상황에 따라 이런 데이터는 제외하기도 합니다. 만약 30번 이상의 주문이 있는 테이블만 추려 데이터 분석을 하려면 어떻게 해야 할까요? 다음은 30번 이상의 주문이 있는 테이블만 그룹화하여 변수 tips_filtered에 저장한 것입니다.<jupyter_code>tips_filtered = tips.\
groupby('size').\
filter(lambda x: x['size'].count() >= 30)<jupyter_output><empty_output><jupyter_text>4.과정 3을 거치고 나면 1,5,6 테이블의 데이터가 제외되었다는 것을 알 수 있습니다.<jupyter_code>print(tips_filtered.shape)
print(tips_filtered['size'].value_counts())<jupyter_output>2    156
3     38
4     37
Name: size, dtype: int64<jupyter_text>11-4 그룹 오브젝트 그룹 오브젝트 살펴보기지금까지는 groupby 메서드에 바로 집계 메서드를 사용하여 결과를 확인했습니다. 즉, groupby 메서드가 반환하는 값인 그룹 오브젝트에 대해서는 언급하지 않았습니다. 이번에는 groupby 메서드의 결괏값인 그룹 오브젝트를 자세히 살펴보겠습니다.  그룹 오브젝트 저장하여 살펴보기 1.다음은 tips 데이터 집합에서 임의로 10개의 데이터를 추출한 것입니다.<jupyter_code>tips_10 = sns.load_dataset('tips').sample(10, random_state=42)
print(tips_10)<jupyter_output>total_bill   tip     sex smoker   day    time  size
24        19.82  3.18    Male     No   Sat  Dinner     2
6          8.77  2.00    Male     No   Sun  Dinner     2
153       24.55  2.00    Male     No   Sun  Dinner     4
211       25.89  5.16    Male    Yes   Sat  Dinner     4
198       13.00  2.00  Female    Yes  Thur   Lunch     2
176       17.89  2.00    Male    Yes   Sun  Dinner     2
192       28.44  2.56    Male    Yes  Thur   Lunch     2
124       12.48  2.52  Female     No  Thur   Lunch     2
9         14.78  3.23    Male     No   Sun  Dinner     2
101       15.38  3.00  Female    Yes   Fri  Dinner     2<jupyter_text>2.groupby 메서드의 결괏값을 출력하면 자료형이 그룹 오브젝트라는 것을 확인할 수 있습니다.<jupyter_code>grouped = tips_10.groupby('sex')
print(grouped)<jupyter_output><pandas.core.groupby.generic.DataFrameGroupBy object at 0x7feb55bab0b8><jupyter_text>3.그룹 오브젝트에 포함된 그룹을 보려면 groups 속성을 출력하면 됩니다. 그러면 sex 열로 그룹화한 데이터프레임의 인덱스를 확인할 수 있습니다. 이 그룹 오브젝트로 집계,변환,필터 작업을 수행하면 되는 것이죠.<jupyter_code>print(grouped.groups)<jupyter_output>{'Male': [24, 6, 153, 211, 176, 192, 9], 'Female': [198, 124, 101]}<jupyter_text>한 번에 그룹 오브젝트 계산하기바로 앞의 실습에서 구한 그룹 오브젝트(grouped)는 smoker, day, time 열과 같은 평균값을 구할 수 없는 열도 포함하고 있습니다. 이런 그룹 오브젝트에 mean 메서드와 같은 집계 메서드를 사용하면 어떻게 될까요? 오류가 발생할까요? 아닙니다! 다행히 파이썬은 자동으로 계산할 수 있는 열을 골라주는 기능을 제공합니다. 따라서 그룹 오브젝트에 mean 메서드를 사용해요 바로 평균값을 구할 수 있습니다. 그룹 오브젝트의 평균 구하기 1.일단 앞에서 만든 그룹 오브젝트(grouped)를 이용하여 평균을 구해 보겠습니다. 그러면 tips 데이터 집합의 모든 열의 평균을 구한 것이 아니라 total_bill, tip, size 열의 평균을 구했다는 것을 알 수 있습니다.<jupyter_code>avgs = grouped.mean()
print(avgs)<jupyter_output>total_bill       tip      size
sex                                   
Male         20.02  2.875714  2.571429
Female       13.62  2.506667  2.000000<jupyter_text>2. tips 데이터 집합의 열을 확인해 보면 평균값을 계산할 수 없는 열인 smoker, day, time 열은 그룹 연산에서 제외되었다는 것을 알 수 있습니다. 이처럼 파이썬은 그룹 연산에 적합한 열을 알아서 골라줍니다.<jupyter_code>print(tips_10.columns)<jupyter_output>Index(['total_bill', 'tip', 'sex', 'smoker', 'day', 'time', 'size'], dtype='object')<jupyter_text>그룹 오브젝트 활용하기이번에는 그룹 오브젝트를 좀더 다양하게 활용하는 방법에 대해 알아보겠습니다. 그룹 오브젝트를 활용하는 방법은 아주 많습니다. 여기에서 실습을 통해 소개할 내용은 그룹 오브젝트에서 '데이터 추출하기'와 '반복문 사용하기'입니다. 만약 그룹 오브젝트를 활용하는 방법을 더 알고 싶다면 다음 웹 사이트를 참고하세요.https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.groupby.html  그룹 오브젝트에서 데이터 추출하고 반복하기 1.만약 그룹 오브젝트에서 특정 데이터만 추출하려면 get_group 메서드를 사용하면 됩니다. 다음은 sex 열로 그룹화한 그룹 오브젝트에 get_group 메서드를 사용하면 됩니다. 다음은 sex 열로 그룹화한 그룹 오브젝트에 get_group 메서드를 사용하여 성별이 여성인 데이터만 추출한 것입니다.<jupyter_code>female = grouped.get_group('Female')
print(female)<jupyter_output>total_bill   tip     sex smoker   day    time  size
198       13.00  2.00  Female    Yes  Thur   Lunch     2
124       12.48  2.52  Female     No  Thur   Lunch     2
101       15.38  3.00  Female    Yes   Fri  Dinner     2<jupyter_text>2.이번에는 그룹 오브젝트를 반복문에 사용해 보겠습니다. sex 열을 기준으로 그룹화한 tips 데이터 집합은 여성 그룹과 남성 그룹으로 나누어져 있습니다. 이 특징을 이용하여 반복문을 사용하면 됩니다. 다음은 각 성별 그룹의 데이터를 반복문을 이용하여 출력한 것입니다.<jupyter_code>for sex_group in grouped:
    print(sex_group)<jupyter_output>('Male',      total_bill   tip   sex smoker   day    time  size
24        19.82  3.18  Male     No   Sat  Dinner     2
6          8.77  2.00  Male     No   Sun  Dinner     2
153       24.55  2.00  Male     No   Sun  Dinner     4
211       25.89  5.16  Male    Yes   Sat  Dinner     4
176       17.89  2.00  Male    Yes   Sun  Dinner     2
192       28.44  2.56  Male    Yes  Thur   Lunch     2
9         14.78  3.23  Male     No   Sun  Dinner     2)
('Female',      total_bill   tip     sex smoker   day    time  size
198       13.00  2.00  Female    Yes  Thur   Lunch     2
124       12.48  2.52  Female     No  Thur   Lunch     2
101       15.38  3.00  Female    Yes   Fri  Dinner     2)<jupyter_text>3. 그런데 과정 2의 결과를 자세히 살펴보면 sex_group으로 넘어온 값이 튜플이라는 것을 알 수 있습니다. 다음은 sex_group의 자세한 정보를 출력한 것입니다.<jupyter_code>for sex_group in grouped:
    print('the type is: {}\n'.format(type(sex_group)))
    print('the length is: {}\n'.format(len(sex_group)))
    

    first_element = sex_group[0]
    print('the first element is: {}\n'.format(first_element))
    print('it has a type of: {}\n'.format(type(sex_group[0])))
    
    second_element = sex_group[1]
    print('the second element is :\n{}\n'.format(second_element))
    print('it has a type of:{}\n'.format(type(second_element)))
          
    print('what we have:')
    print(sex_group)
          
    break<jupyter_output>the type is: <class 'tuple'>

the length is: 2

the first element is: Male

it has a type of: <class 'str'>

the second element is :
     total_bill   tip   sex smoker   day    time  size
24        19.82  3.18  Male     No   Sat  Dinner     2
6          8.77  2.00  Male     No   Sun  Dinner     2
153       24.55  2.00  Male     No   Sun  Dinner     4
211       25.89  5.16  Male    Yes   Sat  Dinner     4
176       17.89  2.00  Male    Yes   Sun  Dinner     2
192       28.44  2.56  Male    Yes  Thur   Lunch     2
9         14.78  3.23  Male     No   Sun  Dinner     2

it has a type of:<class 'pandas.core.frame.DataFrame'>

what we have:
('Male',      total_bill   tip   sex smoker   day    time  size
24        19.82  3.18  Male     No   Sat  Dinner     2
6          8.77  2.00  Male     No   Sun  Dinner     2
153       24.55  2.00  Male     No   Sun  Dinner     4
211       25.89  5.16  Male    Yes   Sat  Dinner     4
176       17.89  2.00  Male    Yes   Sun  Dinner     2
192       28.44  [...]<jupyter_text>여러 열을 사용해 그룹 오브젝트 만들고 계산하기지금까지는 하나의 열을 사용하여 그룹 오브젝트를 만들고 연산을 수행했습니다. 하지만 여러 열을 사용하여 그룹 오브젝트를 만들고 평균값을 구하는 등의 계산도 할 수 있습니다. 그룹 오브젝트 계산하고 살펴보기 1.여러 열을 사용하여 데이터를 그룹화하려면 리스트에 열 이름으 담아 groupby 메서드에 전달하면 된다. 다음은 sex, time 열을 기준으로 데이터를 그룹화하고 평균값을 구한 것입니다.<jupyter_code>bill_sex_time = tips_10.groupby(['sex','time'])
group_avg = bill_sex_time.mean()

print(group_avg)<jupyter_output>total_bill       tip      size
sex    time                                  
Male   Lunch    28.440000  2.560000  2.000000
       Dinner   18.616667  2.928333  2.666667
Female Lunch    12.740000  2.260000  2.000000
       Dinner   15.380000  3.000000  2.000000<jupyter_text>2.과정 1을 거친 group_avg의 자료형을 확인해 보면 데이터프레임이라는 것을 알 수 있습니다. 그리고 변수 group_avg에 포함된 열은 total_bill, tip, size 라는 것도 알 수 있습니다.<jupyter_code>print(type(group_avg))
print(group_avg.columns)<jupyter_output>Index(['total_bill', 'tip', 'size'], dtype='object')<jupyter_text>3.groupt_avg의 자료형은 데이터프레임이라고 했습니다. 그러면 인덱스는 어떻게 구성되어 있을가요? 다음은 group_avg의 인덱스를 출력한 것입니다.<jupyter_code>print(group_avg.index)<jupyter_output>MultiIndex([(  'Male',  'Lunch'),
            (  'Male', 'Dinner'),
            ('Female',  'Lunch'),
            ('Female', 'Dinner')],
           names=['sex', 'time'])<jupyter_text>4.과정 3과 같이 데이터프레임의 인덱스가 MultiIndex인 경우에는 reset_index 메서드를 사용하여 데이터프레임의 인덱스를 새로 부여할 수도 있습니다.<jupyter_code>group_method = tips_10.groupby(['sex', 'time']).mean( ).reset_index( )
print(group_method)<jupyter_output>sex    time  total_bill       tip      size
0    Male   Lunch   28.440000  2.560000  2.000000
1    Male  Dinner   18.616667  2.928333  2.666667
2  Female   Lunch   12.740000  2.260000  2.000000
3  Female  Dinner   15.380000  3.000000  2.000000<jupyter_text>5.reset_index 메서드 대신 as_index 인자를 False로 설정해도 과정 4와 같은 결과를 얻을 수 있습니다.<jupyter_code>group_param = tips_10.groupby(['sex', 'time'], as_index=False).mean( )
print(group_param)<jupyter_output>sex    time  total_bill       tip      size
0    Male   Lunch   28.440000  2.560000  2.000000
1    Male  Dinner   18.616667  2.928333  2.666667
2  Female   Lunch   12.740000  2.260000  2.000000
3  Female  Dinner   15.380000  3.000000  2.000000
{'fraction_non_alphanumeric': 0.0798188370507451, 'fraction_numerical': 0.1322684328430895, 'mean_word_length': 2.5515392597717055, 'pattern_counts': {'":': 2, '<': 122, '<?xml version=': 0, '>': 123, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 19, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '37', 'dir': 'jupyter-structured-clean-dedup', 'id': '412258', 'license': 'MIT', 'n_tokens_mistral': 13619, 'n_tokens_neox': 14405, 'n_words': 2627, 'path': 'Chapter 11.ipynb', 'repo_name': 'goldang01/doit_pandas_study', 'size': '20534'}