【问题标题】:How to find the most frequent progressive digit from a list of 4-digits numbers如何从 4 位数字列表中找到最常见的渐进数字
【发布时间】:2020-05-12 22:13:58
【问题描述】:

我是 Python 编程的新手。从 4 位数字列表中找到最常见的渐进数字的有效且 Pyhtonic 方法是什么?

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

逻辑是观察第一个数字 6 是最常见的。我可以删除数字 7111 以供下一个考虑。

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

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

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

一种简单的方法是将列表转换为 Nx4 矩阵,并为每一列考虑最常见的数字。这可以工作,但我找到了一种非常愚蠢和低效的方法来解决这个问题。有人可以帮忙吗?

编辑:此解决方案的代码(注意:此代码并不总是有效,有些地方是错误的。有关此问题的解决方案,请参阅@MadPhysicist ANSWER)

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])

【问题讨论】:

  • 展示愚蠢的方式。你是新来的。你的方法可能没有你想象的那么愚蠢,特别是如果它有效:)
  • 我赞同上面的评论。恐怕如果我想出一个解决方案,它比你的更愚蠢 :-)。
  • @MadPhysicist 我发布了我在写这篇文章时想到的解决方案。它根本不是 Pythonic,但它可以工作
  • @QuangHoang 也可以看看
  • 我取消了我的投票并删除了我的近距离投票。如果你喜欢我的回答,请告诉我。

标签: python python-3.x numpy frequency


【解决方案1】:

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

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

第 n 个数字(从零开始)可以通过类似的方式获得

nth = (z // 10**n) % 10

使用np.bincount 可以快速完成最频繁的计数,如图所示here

frequentest = np.argmax(np.bincount(nth))

您可以简单地选择在第 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 将返回第一个最大计数的索引,这意味着它将始终选择最小的数字。

您可以通过类似的方式从output 恢复号码

>>> output
array([1, 1, 1, 6])
>>> (output * 10**np.arange(output.size)).sum()
6111

你也可以只获取z的剩余元素:

>>> z[0]
6111

【讨论】:

  • 我了解您的解决方案,但对我来说阅读和使用它看起来非常复杂。我想我会尝试优化我的代码。无论如何,我很高兴您找到了另一种解决方法,非常感谢您抽出宝贵的时间:))
  • @G.Guidi 如果你告诉我你认为什么很复杂,我很乐意解释。在我看来,这比你的要简单得多,但这可能是因为我在 numpy 中思考了很长时间:)
  • 我的印象是你不需要循环。只需使用i=1 做一次。
  • @QuangHoang。真的。我认为 OP 对这个解决方案有足够的问题,所以我用详细的评论而不是更多的代码来扩展它:)
  • @G.Guidi。我添加了非常详细的 cmets 来帮助您浏览代码并了解其工作原理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-06-06
  • 1970-01-01
  • 2015-11-29
  • 2014-08-19
  • 2021-03-27
  • 2021-09-22
  • 1970-01-01
相关资源
最近更新 更多