Во-первых, у вас, похоже, есть ошибка в отступе - for val in data.values():
не должно быть вложено в for bins in range(0, max_salary+1, bin_width):
- поэтому вы получаете более длинный список значений.
Во-вторых, ваша логика немного устареларазличными способами - вы сохраняете переменную count, которая устанавливается в ноль только один раз, в начале функции.for n in bin_list:
перебирает значения в bin_list
, но затем вы умножаете n
на bin_width
, что не имеет смысла.Вы можете изменить это, используя range(n_bins)
, чтобы пройти через индексы bin_lists
, например:
def wealth_distribution(data, n_bins, max_salary):
sal_list = [0] * n_bins
bin_list = []
bin_width = int(max_salary/n_bins)
for bins in range(0, max_salary+1, bin_width):
bin_list.append(bins)
for val in data.values():
if val['salary'] == None:
continue
for i in range(n_bins):
if math.floor(i*bin_width)<=float(val['salary'])<math.floor((i+1)*bin_width):
sal_list[i] += 1
return sal_list
Но при ближайшем рассмотрении bin_list
на самом деле здесь не имеет смысла.Функция может быть уменьшена до:
def wealth_distribution(data, n_bins, max_salary):
sal_list = [0] * n_bins
bin_width = max_salary/n_bins
for val in data.values():
if val['salary'] == None:
continue
bin_index = int(float(val["salary"]) / bin_width)
if bin_index < n_bins:
sal_list[bin_index] += 1
else: # salary = max_salary
sal_list[n_bins-1] += 1
return sal_list
Приведенная выше функция рассчитывает индекс бина, а не циклически просматривает бины или индексы.Я также удалил math.floor
s, так как они кажутся ненужными и могут привести к некоторым ситуациям, когда небольшая ошибка округления может привести к тому, что некоторые зарплаты не будут классифицированы.
Вы могли бы упростить дальнейшее использование collections.Counter
:
from collections import Counter
def wealth_distribution(data, n_bins, max_salary):
bin_width = max_salary / n_bins
bins = Counter(min(int(float(val["salary"]) // bin_width), n_bins-1)
for val in data.values())
return [bins[i] for i in range(n_bins)]
В numpy
есть функция histogram
, которая также делает то, что вы хотите, и в качестве бонуса предоставляет массив границ корзины.
import numpy as np
salaries = [float(val["salary"]) for val in data.values()]
sal_list, bin_list = np.histogram(salaries, bins=5, range=(0, 100))
А если вы хотите использовать pandas
... (может быть полезно для других операций с теми же данными)
import pandas as pd
def wealth_distribution(data, n_bins, max_salary):
df = pd.DataFrame(data).transpose()
bin_width = max_salary / n_bins
df["salary_bin"] = (pd.to_numeric(df["salary"]) // bin_width).clip(upper=n_bins-1)
counts = df["salary_bin"].value_counts()
return counts.reindex(range(n_bins), fill_value=0).values