Contando índices em pandas

8

Sinto que essa é uma pergunta rudimentar, mas sou muito nova nisso e simplesmente não consegui decifrá-la / encontrar a resposta.

Em última análise, o que estou tentando fazer aqui é contar valores exclusivos em uma determinada coluna e determinar quais desses valores únicos têm mais de um valor exclusivo em uma coluna correspondente.

Portanto, para esses dados, o que estou tentando determinar é "quem" possui "mais de um recibo" para todas as compras e, em seguida, determine as mesmas informações com base em cada categoria de produto.

Minha abordagem até agora:

Temos um conjunto de dados como este:

receipt,name,etc,category
1,george,xxx,fish
1,george,xxx,cat
2,george,xxx,fish
3,bill,xxx,fish
3,bill,xxx,dog
4,jill,xxx,cat
5,bill,xxx,cat
5,bill,xxx,cat
5,bill,xxx,dog
6,george,xxx,fish

Então eu posso fazer isso:

df.set_index(['name','receipt'])

E obtenha o mais interessante

                etc category
name   receipt
george 1        xxx     fish
       1        xxx      cat
       2        xxx     fish
bill   3        xxx     fish
       3        xxx      dog
jill   4        xxx      cat
bill   5        xxx      cat
       5        xxx      cat
       5        xxx      dog
george 6        xxx     fish

Neste ponto, parece-me que os dados são fáceis de trabalhar, mas ainda não os descobri.

Uma coisa que é interessante para mim é que, se eu classificar os dados por nome antes de indexá-los, os dados serão agrupados por nome. Nos dois casos, o índice é o mesmo, então não sei como jogar com a representação dos dados após a indexação.

É fácil encontrar os dados por categoria usando

>>> orders.loc[orders['category'] == 'fish']
                etc category
name   receipt
george 1        xxx     fish
       2        xxx     fish
bill   3        xxx     fish
george 6        xxx     fish

Mas o que não consigo descobrir é como dizer aos pandas "Encontre-me a lista de nomes com mais de um recibo".

Perguntas menores:

  • Qual é o "caminho dos pandas" para obter o comprimento dos nomes como parte do índice? Suponho que eu poderia transformar a namecoluna em um conjunto e obter o comprimento disso. Mas estou curioso sobre índices.

Editar / Atualizar

Obrigado por essas respostas! Aqui estão os esclarecimentos sobre o que estou procurando:

Estou tentando encontrar "clientes recorrentes": pessoas com mais de um recibo.

Portanto, meu conjunto de todos os clientes seria:

names: ['george','bill','jill'], ratio: 1.0

Meus clientes recorrentes:

names: ['george','bill'], ratio 0.66

Todos os clientes 'peixe':

names: ['george','bill'], ratio: 0.666

Meus clientes repetidos 'peixe':

names: ['george'], ratio: 0.333

Acho que os exemplos apresentados parecem úteis, mas fique à vontade para adicionar qualquer coisa.

Sr. Hasquestions
fonte
você pode postar um conjunto de dados resultante (esperado) desejado?
MaxU

Respostas:

5

Eu acho que talvez você esteja procurando:

receipts_by_name_x_cat = df.groupby(['name','category']).count()

Ou, se você quiser apenas o total em todas as categorias:

receipts_by_name = df.groupby(['name']).count()

Em seguida, você pode pesquisar aqueles que têm mais de um:

receipts_by_name[receipts_by_name['receipt']>1]

E, você pode encontrar o tamanho de um índice digitando:

len(df.index.get_level_values(0))

Supondo que o nome fosse a primeira coluna do índice (caso contrário, substitua 1, 2 etc.)

atkat12
fonte
Isso é extremamente útil. Eu escrevi minha pergunta errada embora. "Mais de um recibo" deve ser "Mais de uma transação, o que significa que eles têm mais de um recibo exclusivo ".
Sr. Hasquestions
Fico feliz em ouvir isso. Re: sua pergunta, como são os dois diferentes? o que define um recibo exclusivo - a coluna 'recibo' é o ID do recibo? e a categoria são todos os itens que eles compraram nesse recibo? Nesse caso, você pode tentar receipts_by_name = df.groupby(['name']).unique()responder a coluna "recibo", eu acho. Você só precisa aplicar uma função groupby diferente.
atkat12
Certo, uma maneira de pensar sobre isso é que cada linha no conjunto de dados representa um item de linha em uma compra; portanto, o recebimento é o "ID do recebimento" dessa transação. Por exemplo, Bill comprou dois itens de gato durante a transação nº 5 e ele é responsável pela transação nº 2. Portanto, ele é um "comprador repetido", mas não é um "comprador repetido", pois suas duas compras ocorreram durante a mesma transação.
Sr. Hasquestions
3

Não está claro o que exatamente você está tentando alcançar (seria útil entender seus objetivos se você publicasse os conjuntos de dados desejados / esperados) ...

Mas vou tentar adivinhar;)

Dados:

In [100]: df
Out[100]:
   receipt    name  etc category
0        1  george  xxx     fish
1        1  george  xxx      cat
2        2  george  xxx     fish
3        3    bill  xxx     fish
4        3    bill  xxx      dog
5        4    jill  xxx      cat
6        5    bill  xxx      cat
7        5    bill  xxx      cat
8        5    bill  xxx      dog
9        6  george  xxx     fish

Configurando a coluna virtual count, mostrando o número de linhas agrupadas namee filtrando (consultando) usando o .query()método:

In [101]: (df.assign(count=df.groupby('name').receipt.transform('size'))
     ...:    .query("category in ['dog','cat'] and count > 1"))
     ...:
Out[101]:
   receipt    name  etc category  count
1        1  george  xxx      cat      4
4        3    bill  xxx      dog      5
6        5    bill  xxx      cat      5
7        5    bill  xxx      cat      5
8        5    bill  xxx      dog      5

ou você pode agrupar por várias colunas e filtrar os grupos resultantes:

In [102]: df.groupby(['name','category']).filter(lambda x: len(x) > 2)
Out[102]:
   receipt    name  etc category
0        1  george  xxx     fish
2        2  george  xxx     fish
9        6  george  xxx     fish
MaxU
fonte