개발/Python

[파이썬] sql에서 'count(distinct)'를 Pandas에서 하는 방법

MinorMan 2023. 1. 21. 22:56
반응형

<질문>

여러 데이터베이스가 있으므로 Pandas를 데이터베이스 대체물로 사용하고 있습니다(Oracle,SQL Server등), 일련의 명령을 SQL과 동일하게 만들 수 없습니다.

일부 열이 있는 DataFrame에 로드된 테이블이 있습니다.

YEARMONTH, CLIENTCODE, SIZE, etc., etc.

SQL에서 연간 다른 클라이언트 수를 계산하려면 다음과 같습니다.

SELECT count(distinct CLIENTCODE) FROM table GROUP BY YEARMONTH;

결과는

201301    5000
201302    13245

Pandas에서 어떻게 할 수 있습니까?


<답변1>

나는 이것이 당신이 원하는 것이라고 믿습니다.

table.groupby('YEARMONTH').CLIENTCODE.nunique()

예:

In [2]: table
Out[2]: 
   CLIENTCODE  YEARMONTH
0           1     201301
1           1     201301
2           2     201301
3           1     201302
4           2     201302
5           2     201302
6           3     201302

In [3]: table.groupby('YEARMONTH').CLIENTCODE.nunique()
Out[3]: 
YEARMONTH
201301       2
201302       3

<답변2>

여기에 또 다른 방법이 있으며 훨씬 간단합니다. 데이터 프레임 이름이daat그리고 열 이름은YEARMONTH:

daat.YEARMONTH.value_counts()

<답변3>

흥미롭게도 매우 자주len(unique())보다 몇 배(3x-15x) 빠릅니다.nunique().


<답변4>

저도 사용중입니다nunique그러나 다음과 같은 집계 함수를 사용해야 하는 경우 매우 유용합니다.'min', 'max', 'count' or 'mean'등.

df.groupby('YEARMONTH')['CLIENTCODE'].transform('nunique') #count(distinct)
df.groupby('YEARMONTH')['CLIENTCODE'].transform('min')     #min
df.groupby('YEARMONTH')['CLIENTCODE'].transform('max')     #max
df.groupby('YEARMONTH')['CLIENTCODE'].transform('mean')    #average
df.groupby('YEARMONTH')['CLIENTCODE'].transform('count')   #count

<답변5>

모든 열에 대한 고유한 값 수를 얻으려면(CLIENTCODE귀하의 경우), 우리는 사용할 수 있습니다nunique. 입력을 사전으로 전달할 수 있습니다.agg다른 열에 대한 집계와 함께 함수:

grp_df = df.groupby('YEARMONTH').agg({'CLIENTCODE': ['nunique'],
                                      'other_col_1': ['sum', 'count']})

# to flatten the multi-level columns
grp_df.columns = ["_".join(col).strip() for col in grp_df.columns.values]

# if you wish to reset the index
grp_df.reset_index(inplace=True)

<답변6>

사용crosstab, 다음보다 더 많은 정보를 반환합니다.groupbynunique:

pd.crosstab(df.YEARMONTH,df.CLIENTCODE)
Out[196]:
CLIENTCODE  1  2  3
YEARMONTH
201301      2  1  0
201302      1  2  1

약간의 수정 후 결과는 다음과 같습니다.

pd.crosstab(df.YEARMONTH,df.CLIENTCODE).ne(0).sum(1)
Out[197]:
YEARMONTH
201301    2
201302    3
dtype: int64

<답변7>

다음은 여러 열에 대해 고유한 수를 갖는 접근 방식입니다. 몇 가지 데이터가 있습니다.

data = {'CLIENT_CODE':[1,1,2,1,2,2,3],
        'YEAR_MONTH':[201301,201301,201301,201302,201302,201302,201302],
        'PRODUCT_CODE': [100,150,220,400,50,80,100]
       }
table = pd.DataFrame(data)
table

CLIENT_CODE YEAR_MONTH  PRODUCT_CODE
0   1       201301      100
1   1       201301      150
2   2       201301      220
3   1       201302      400
4   2       201302      50
5   2       201302      80
6   3       201302      100

이제 관심 있는 열을 나열하고 약간 수정된 구문으로 groupby를 사용합니다.

columns = ['YEAR_MONTH', 'PRODUCT_CODE']
table[columns].groupby(table['CLIENT_CODE']).nunique()

우리는 다음을 얻습니다.

YEAR_MONTH  PRODUCT_CODE CLIENT_CODE
1           2            3
2           2            3
3           1            1

<답변8>

새로운 Pandas 버전을 사용하면 데이터 프레임으로 쉽게 얻을 수 있습니다.

unique_count = pd.groupby(['YEARMONTH'], as_index=False).agg(uniq_CLIENTCODE=('CLIENTCODE', pd.Series.count))

<답변9>

이제 당신도 사용할 수 있습니다dplyr이를 수행하는 Python의 구문:

>>> from datar.all import f, tibble, group_by, summarise, n_distinct
>>>
>>> data = tibble(
...     CLIENT_CODE=[1,1,2,1,2,2,3],
...     YEAR_MONTH=[201301,201301,201301,201302,201302,201302,201302]
... )
>>>
>>> data >> group_by(f.YEAR_MONTH) >> summarise(n=n_distinct(f.CLIENT_CODE))
   YEAR_MONTH       n
       
0      201301       2
1      201302       3

<답변10>

피벗 테이블을 만들고누니크시리즈 기능:

ID = [ 123, 123, 123, 456, 456, 456, 456, 789, 789]
domain = ['vk.com', 'vk.com', 'twitter.com', 'vk.com', 'facebook.com',
          'vk.com', 'google.com', 'twitter.com', 'vk.com']
df = pd.DataFrame({'id':ID, 'domain':domain})
fp = pd.pivot_table(data=df, index='domain', aggfunc=pd.Series.nunique)
print(fp)

산출:

               id
domain
facebook.com   1
google.com     1
twitter.com    2
vk.com         3

<답변11>

  • 연간 다른 클라이언트 및 크기의 수를 얻기 위해(예:여러 열), 열 목록을 사용합니다.
    df.groupby('YEARMONTH')[['CLIENTCODE', 'SIZE']].nunique()
    
  • 실제로 위 코드의 결과는 SQL 구문을 사용하여 얻을 수 있습니다.df사용pandasql(SQL 구문을 사용하여 pandas DataFrames를 쿼리할 수 있는 pandas 기반 모듈).
    #! pip install pandasql from pandasql import sqldf sqldf(""" SELECT COUNT(DISTINCT CLIENTCODE), COUNT(DISTINCT SIZE) FROM df GROUP BY YEARMONTH """)
  • YEARMONTH를 열로 유지하려는 경우(예: 다음 SQL 쿼리의 아날로그)
    SELECT YEARMONTH, COUNT(DISTINCT CLIENTCODE), COUNT(DISTINCT SIZE) FROM df GROUP BY YEARMONTH
    pandas에서는 다음과 같습니다(설정as_index에게False):
    df.groupby('YEARMONTH', as_index=False)[['CLIENTCODE', 'SIZE']].nunique()
    
  • 집계된 열에 사용자 지정 이름을 설정해야 하는 경우(즉, 다음 SQL 쿼리와 유사함):
    SELECT YEARMONTH, COUNT(DISTINCT CLIENTCODE) AS `No. clients`, COUNT(DISTINCT SIZE) AS `No. size` FROM df GROUP BY YEARMONTH
    팬더에서 명명된 집계 사용:
    ( df.groupby('YEARMONTH', as_index=False) .agg(**{'No. clients':('CLIENTCODE', 'nunique'), 'No. size':('SIZE', 'nunique')}) )
반응형