如何从 4 位数字列表中找到最频繁的累进数字

How to find the most frequent progressive digit from a list of 4-digits numbers

我在 Python 编程方面还很陌生。从 4 位数字列表中找到最频繁的渐进数字的有效和 Pyhtonic 方法是什么?

假设我有以下列表:[6111, 7111, 6112, 6121, 6115, 6123]

逻辑是观察第一个数字 6 出现频率最高。为了接下来的考虑,我可以删除数字 7111。

对于第二个数字,我考虑了新的候选 [6111, 6112, 6121, 6115, 6123],我观察到 1 是最常见的数字,依此类推。

在算法结束时,我将只剩下 1 个列表。

如果有 2 个或更多数字出现相同的数字,我可以在所有数字中随机选择较小的一个。

一种简单的方法是将列表转换为 Nx4 矩阵,并为每一列考虑最频繁的数字。这可能行得通,但我发现解决这个问题的方法非常愚蠢且效率低下。有人可以帮忙吗?

编辑:我的这个解决方案的代码(注意:这个代码并不总是有效,有些地方是错误的。这个问题的解决方案请参考@MadPhysicist 的回答)

import numpy as np
import pandas as pd
from collections import Counter



numbers_list = [6111, 7111, 6112, 6121, 6115, 6123]

my_list = []

for number in numbers_list:
    digit_list = []
    for c in str(number):
       digit_list.append(c)
    my_list.append(digit_list)


matrix = np.array(my_list)

matrix0 = matrix

my_counter = Counter(matrix.T[0]).most_common(1)
i=0
for digit0 in matrix.T[0]:
    if digit0 != my_counter[0][0]:
        matrix0 = np.delete(matrix, i, 0)
    i += 1
matrix = matrix0

matrix1 = matrix
my_counter = Counter(matrix.T[1]).most_common(1)
i=0
for digit1 in matrix.T[1]:
    if digit1 != my_counter[0][0]:
        matrix1 = np.delete(matrix, i, 0)
    i += 1
matrix = matrix1

matrix2 = matrix
my_counter = Counter(matrix.T[2]).most_common(1)
i=0
for digit2 in matrix.T[2]:
    if digit2 != my_counter[0][0]:
        matrix2 = np.delete(matrix, i, 0)
    i += 1

matrix = matrix2

matrix3 = matrix
my_counter = Counter(matrix.T[3]).most_common(1)
i=0
for digit3 in matrix.T[3]:
    if digit3 != my_counter[0][0]:
        matrix3 = np.delete(matrix, i, 0)
    i += 1
matrix = matrix3

print (matrix[0])

您转换为 numpy 数组的想法是可靠的。您不需要预先拆分它。一系列掩码和直方图将相当快地减少阵列。

z = np.array([6111, 7111, 6112, 6121, 6115, 6123])

第 n 位数字(从零开始)可以通过类似

的方式获得
nth = (z // 10**n) % 10

使用 np.bincount as shown here:

可以快速完成最频繁的计数
frequentest = np.argmax(np.bincount(nth))

您可以 select 具有第 n 个数字的元素

mask = nth == frequentest

所以现在 运行 这在 n 的循环中(向后):

# Input array
z = np.array([6111, 7111, 6112, 6121, 6115, 6123])

# Compute the maximum number of decimal digits in the list.
# You can just manually set this to 4 if you prefer
n = int(np.ceil(np.log10(z + 1).max()))

# Empty output array
output = np.empty(n, dtype=int)

# Loop over the number of digits in reverse.
# In this case, i will be 3, 2, 1, 0.
for i in range(n - 1, -1, -1):

    # Get the ith digit from each element of z
    # The operators //, ** and % are vectorized: they operate
    # on each element of an array to return an array
    ith = (z // 10**i) % 10

    # Count the number of occurrences of each number 0-9 in the ith digit
    # Bincount returns an array of 10 elements. counts[0] is the number of 0s,
    # counts[1] is the number of 1s, ..., counts[9] is the number of 9s
    counts = np.bincount(ith)

    # argmax finds the index of the maximum element: the digit with the
    # highest count
    output[i] = np.argmax(counts)

    # Trim down the array to numbers that have the requested digit in the
    # right place. ith == output[i] is a boolean mask. It is 1 where ith
    # is the most common digit and 0 where it is not. Indexing with such a
    # mask selects the elements at locations that are non-zero.
    z = z[ith == output[i]]

碰巧,如果有多个可用,np.argmax 将 return 第一个最大计数的索引,这意味着它将始终 select 最小的数字。

您可以使用

之类的东西从 output 恢复号码
>>> output
array([1, 1, 1, 6])
>>> (output * 10**np.arange(output.size)).sum()
6111

你也可以只得到z的剩余元素:

>>> z[0]
6111