Get the most frequent and least frequent element from a list, plus the largest and smallest

Asked

Viewed 747 times

0

How can I find the highest and lowest number, the most frequent and the least frequent, in any list?

Current code:

import random

maiorNumero = 0
menorNumero = 100

arrayNumeros = []

print("Os numeros gerados foram: \n")
for x in range(1,11):
    arrayNumeros.append(random.randint(0,10))
    print(arrayNumeros)


print(" ")
print (f"O maior número gerado foi: {maiorNumero}\n")
print (f"O menor número gerado foi: {menorNumero}\n")
print(f"O número sorteado mais vezes foi: {maisSorteado}\n")
print(f"O número sorteado mais vezes foi: {menosSorteado}\n")
  • Yesterday I answered a similar question. See help: https://answall.com/a/456064/137387

4 answers

2

To count the frequency of all elements in a list, just use a Counter. Then, to get the most and least frequent, use the method most_common:

import random
from collections import Counter

# gera 10 números aleatórios entre 0 e 10
numeros = random.choices(range(11), k=10)
print(f'Os numeros gerados foram: {numeros}')

frequencias = Counter(numeros).most_common()
mais_frequente, menos_frequente = frequencias[0], frequencias[-1]
print(f'O número que ocorre mais vezes é {mais_frequente[0]}, ocorrendo {mais_frequente[1]} vezes')
print(f'O número que ocorre menos vezes é {menos_frequente[0]}, ocorrendo {menos_frequente[1]} vezes')

most_common returns a list of tuples, each tuple containing the element and the respective amount of times it occurs. Thus, the most frequent is the first element of this list, and the least frequent is the last.

The other answers suggest using the method count list, but this is an inefficient way, because each time count is called, it runs through the entire list to get the count of a single element. That is, you will be going through the list several times, to get the count of all elements.
Worse, for an element that occurs more than once, you will be getting the count of it several times. This is not only unnecessary, but extremely inefficient - of course for small lists will not make so much difference, but for larger lists, the difference is striking. And it doesn’t even have to be that big: doing a test with a list of 2000 elements, the Counter was much faster (a few hundred times faster). Increase to 10 thousand elements, the difference becomes even greater.

When you go through a list several times without need, you are creating a variation of the call "Shlemiel the Painter’s Algorithm". The problem is that we often only test with small lists and do not notice the problem, but if you do it in large volumes of data, then it will make all the difference.

So, use a Counter It is better because you only go through the list once, getting the count of all the elements. But we still have to solve the case of draws, when more than one element is the most (or least) frequent. How most_common already returns the elements in the order (from most frequent to least frequent), just go through the list from the beginning (or the end) and stop when you find a different count:

frequencias = Counter(numeros).most_common()
mais_frequente, menos_frequente = frequencias[0], frequencias[-1]

print(f'Números mais frequentes (ocorrem {mais_frequente[1]} vezes)')
for f in frequencias:
    if f[1] == mais_frequente[1]:
        print(f[0])
    else:
        break
print(f'Números menos frequentes (ocorrem {menos_frequente[1]} vezes)')
for f in reversed(frequencias):
    if f[1] == menos_frequente[1]:
        print(f[0])
    else:
        break

Finally, also note that to generate a list of 10 random numbers between 0 and 10, you can use random.choices, passing by range(11), that generates a range with the numbers between 0 and 10 (since a range does not include the final value). Remembering that random.choices is available from Python 3.6. For earlier versions, you can simplify your loop, trading it for a comprehensilist on, much more succinct and pythonic:

# gera 10 números aleatórios entre 0 e 10
numeros = [ random.randint(0, 10) for _ in range(10) ]

You can still optimize more, because if you use the Counter to get the frequencies, and then use max and min to get the largest and smallest element, you will be going through the list 3 times (one for the Counter, another to max and another to min). If you want to do everything in one loop, then you will have to do everything manually (but depending on the size of the list, it may make up for not having to travel it several times):

contagens = Counter()
maior = float('-inf') # infinito negativo
menor = float('inf') # infinito

for n in numeros:
    contagens.update([n])
    if n > maior:
        maior = n
    if n < menor:
        menor = n

frequencias = contagens.most_common()
mais_frequente, menos_frequente = frequencias[0], frequencias[-1]
print(f'Números mais frequentes (ocorrem {mais_frequente[1]} vezes)')
for f in frequencias:
    if f[1] == mais_frequente[1]:
        print(f[0])
    else:
        break
print(f'Números menos frequentes (ocorrem {menos_frequente[1]} vezes)')
for f in reversed(frequencias):
    if f[1] == menos_frequente[1]:
        print(f[0])
    else:
        break

print(f'O maior número é {maior}')
print(f'O menor número é {menor}')

This loop is a little less efficient than using the Counter directly, but still, much faster than use set and/or count.

1

In python, when we have a list and want to know the highest value, we can use the max method. Follows the documentation for reference.

So, using your code, to find the highest value, we can simply use the max function.

print("O maior número gerado foi: {}".format(max(arrayNumeros)))
print("O menor número gerado foi: {}".format(min(arrayNumeros)))

When you say you want to show the elements that most repeat themselves, we are referring to the fashion of a set. We must be careful because the element that repeats most can be more than one, in this case the return must be a set returning the elements that repeat most.

print("O número sorteado mais vezes foi: {}".format(max(set(arrayNumeros), key=arrayNumeros.count)))
print("O número sorteado menos vezes foi: {}".format(min(set(arrayNumeros), key=arrayNumeros.count)))

If using the python >= 3.8 to find all the fashions of a set can be used the following command:

from statistics import multimode
arrayNumeros = [3,9,1,9,7,8,10,4,5,4]
multimode(arrayNumeros)
#[9, 4]
  • Right, I understand perfectly! And to know which number was most drawn and the least drawn?

  • Is in the answer.

  • Excuse my lack of attention, I understood perfectly! And in case you want to represent this set of items? I do with the loop For?

  • I updated the answer.

0

Just use the functions min and max for the smallest and greatest value of a list or any other iterable object such as tuples, dicts, sets, etc. See code below:

import random

# Gera uma lista com dez número aleatórios entre [0-10]
numeros = [random.randint(0, 10) for x in range(11)]

# Obtém o menor e maior valor da lista.
menor = min(numeros)
maior = max(numeros)

print("Os numeros gerados foram:", *numeros)
print ("O maior número gerado foi:", maior)
print ("O menor número gerado foi:", menor)

To find out which was the most drawn and least drawn value use the method count to count the number of times a value appears in the list. See the example below:

# O código abaixo obtém o valor que mais se repete e o que menos se repete na lista.

mais, menos = numeros[0], numeros[0]

for numero in numeros:
    mais = numero if numeros.count(numero) > numeros.count(mais) else mais
    menos = numero if numeros.count(numero) < numeros.count(menos) else menos
  • Right, I understand perfectly! E to find out which number was most drawn and the least drawn?

  • I put in the answer how to count the amount of elements in a list.

0

Simpler than the other answers, you can use max and min for everything. These functions have a parameter key that can be passed to pick up the number with more/less occurrences.

print(max(numeros))
print(min(numeros))
print(max(numeros, key=numeros.count))
print(min(numeros, key=numeros.count))

Browser other questions tagged

You are not signed in. Login or sign up in order to post.