Os pandas contam o equivalente (distinto)

289

Estou usando o pandas como um substituto do db, pois tenho vários bancos de dados (oracle, mssql, etc.) e não consigo fazer uma sequência de comandos para um equivalente SQL.

Eu tenho uma tabela carregada em um DataFrame com algumas colunas:

YEARMONTH, CLIENTCODE, SIZE, .... etc etc

No SQL, contar a quantidade de clientes diferentes por ano seria:

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

E o resultado seria

201301    5000
201302    13245

Como posso fazer isso em pandas?

Adriano Almeida
fonte
Eu fiz table.groupby (['YEARMONTH']) ['CLIENTCODE']. Unique () e vi duas séries indexadas por YEARMONTH e com todos os valores exclusivos. Como contar a quantidade de valores em cada série?
Adriano Almeida
Para alguns, value_countspode ser a resposta que você está procurando: pandas.pydata.org/pandas-docs/stable/generated/…
sachinruk 16/17

Respostas:

434

Eu acredito que é isso que você quer:

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

Exemplo:

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
Dan Allan
fonte
2
E se eu tiver várias colunas que quero que sejam únicas juntas, como em .drop_duplicates (subconjunto = ['col1', 'col2'])?
ErnestScribbler #
4
Como acessar essa contagem exclusiva. Como não há nome de coluna
Tarun Khaneja
Muito obrigado, usei esse estilo na saída de nova amostra. df_watch_record.resample ('M'). user.nunique () conta o número de usuários únicos que assistiram filmes por mês.
Mehdi Kazemi
1
e classifique-os com table.groupby ('YEARMONTH'). CLIENTCODE.nunique (). sort_values ​​(ascending = False)
wllbll
É possível recuperar o identificador do grupo depois nunique? Por mais que eu tente, não consigo encontrar uma maneira, pois o resultado desta resposta é a Series, não a DataFrame.
Josh Hansen
93

Aqui está outro método, muito simples, digamos que o nome do seu quadro de dados seja daate o nome da coluna sejaYEARMONTH

daat.YEARMONTH.value_counts()
StatguyUser
fonte
1
Eu gosto desta resposta. Como posso usar esse método se o nome da minha coluna tiver um '.' nele (por exemplo, 'ck.Class')? Graças
5
daat ['ck.Class']. value_counts ()
StatguyUser
28
Isso não aborda a pergunta feita.
Aaron Schumacher
6
isso contando o número de observações dentro de cada grupo, não o valor exclusivo de uma determinada coluna que cada grupo possui.
Jason Goal
2
Esta é a resposta incorreta; não reflete o DISTINCTrequisito da pergunta! Além disso, não inclui contagens de NaN!
Corey Levinson
47

Curiosamente, muitas vezes len(unique())é algumas vezes (3x-15x) mais rápido que nunique().

Roman Kh
fonte
11
Você quis dizer isso? .CLIENTCODE.apply(lambda x: len(x.unique())), a partir daqui
user4015990 03/12/2015
6
@ user32185 você teria que fazer uma applyligação com uma lambda. Por exemplo df.groupby('YEARMONTH')['CLIENTCODE'].apply(lambda x: x.unique().shape[0]),.
3novak
3
Sintaxe não é totalmente clara, eu usei len(df['column'].unique())nenhuma necessidade para a função lambda
mlh351
Eu recebi TypeError: object of type 'method' has no len()do Chen'scomentário, 3novak'strabalhei para mim.
Jason Goal
4

Usando crosstab, isso retornará mais informações do quegroupby nunique

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

Depois de um pouco de modificação, produza o resultado

pd.crosstab(df.YEARMONTH,df.CLIENTCODE).ne(0).sum(1)
Out[197]: 
YEARMONTH
201301    2
201302    3
dtype: int64
YOBEN_S
fonte
Como posso exportar isso como duas colunas YEARMONTHe count. Também posso definir a contagem em ordem decrescente?
Murtaza Haji
3

Também estou usando, nuniquemas será muito útil se você precisar usar uma função agregada como'min', 'max', 'count' or 'mean' etc.

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
Gangaraju
fonte
0

Com a nova versão do pandas, é fácil obter o dataframe

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

Aqui, uma abordagem para ter contagem distinta em várias colunas. Vamos ter alguns dados:

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

Agora, liste as colunas de interesse e use groupby em uma sintaxe ligeiramente modificada:

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

Nós obtemos:

YEAR_MONTH  PRODUCT_CODE CLIENT_CODE        
1           2            3
2           2            3
3           1            1
Ramon
fonte
0

Distinta da coluna junto com agregações em outras colunas

Para obter o número distinto de valores para qualquer coluna ( CLIENTCODEno seu caso), podemos usar nunique. Podemos passar a entrada como um dicionário na aggfunção, juntamente com agregações em outras colunas:

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)
Vivek Payasi
fonte