【问题标题】:Benford's Law Plotting in Python 3.5.2Python 3.5.2 中的本福德定律绘图
【发布时间】:2017-03-13 03:59:25
【问题描述】:

我被分配的一项任务难住了,该任务要求我输出从 CSV 文件中读取的数据集...

...根据本福德定律,得到如下条形图:

Benford 条形图示例

这是我目前得到的代码:

import matplotlib.pyplot as plt
import math
import csv
import locale

with open("immigrants.csv", newline='') as csvfile:
    immidata = csv.reader(csvfile)
    X_labels = []
    Y = []
    for row in immidata:
        X_labels.append(row[0])
        Y.append(locale.atoi(row[1]))

numbers = [float(n) for n in range(1, 10)]
benford = [math.log10(1 + 1 / d) for d in numbers]
plt.plot(numbers, benford, 'ro', label = "Benford's Law")
plt.bar(numbers, range(1, 11), align = 'left', normed = True, 
    rwidth = 0.7, label = "Actual data")
plt.bar(benford, range(1, 11), align = 'left', normed = True, 
    rwidth = 0.7, label = "Predicted data")
plt.title("Immigrants in countries")
plt.xlabel("Digit")
plt.ylabel("Probability")
plt.grid(True)
plt.xlim(0, 10)
plt.xticks(numbers)
plt.legend()
plt.show()

以下是 CSV 文件中的一些信息,其中显示了每个国家/地区的移民人数(分别为国家、移民人数、世界移民总数的百分比和移民占全国人口的百分比):

United States,"45,785,090",19.8,14.3
Russia,"11,048,064",4.8,7.7
Germany,"9,845,244",4.3,11.9
Saudi Arabia,"9,060,433",3.9,31.4
United Arab Emirates,"7,826,981",3.4,83.7
United Kingdom,"7,824,131",3.4,12.4

我现在的输出:

line 19, in <module>
  Y.append(locale.atoi(row[1]))
line 321, in atoi
  return int(delocalize(string))
ValueError: invalid literal for int() with base 10: 'Number of
immigrants'

Process finished with exit code 1

我对此还比较陌生,因此非常感谢任何有助于我获得输出的建议!

谢谢!

Output

需要看起来像样本的输出。

【问题讨论】:

  • 该行中有多个逗号,因此split(",") 返回超过 2 个项目。您可能需要查看 csv 模块,该模块提供了对 csv 文件的适当处理。
  • 我以前从未使用过 csv 模块...在我的情况下我将如何使用它?
  • 尝试阅读我链接到的文档 - 特别是查看csv.reader。如果您遇到困难,请回到 SO 来解决问题。如果您证明您已经尝试过,您将获得更多帮助。
  • 我有。亲自尝试后,我打印了整个文件,但每个单词后面都加了逗号。
  • 这个问题是关于绘制或读取数据还是关于本福德定律?

标签: python csv matplotlib plot bar-chart


【解决方案1】:

这是一个使用 pandas 的解决方案:

这是本福德定律与移民人数的对比

编辑: 您的文件的标题行可能由 num_immigrants 列中的字符串“移民人数”指示。删除读取数据行中的header=None 选项。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# set the width of the bars, you're gonna have to massage this
width = 0.35

immi = pd.read_csv('immigrants.csv')

# name columns
immi.columns = ['country', 'num_immigrants', 'perc_world', 'perc_nat_pop']

# convert num_immigrants to float
immi.num_immigrants=  immi.num_immigrants.str.replace(',', '').apply(float)
total = immi.num_immigrants.sum()

# scale the immigration to between 0 and 1
immi['immi_scaled'] = immi['num_immigrants'].apply(lambda x: x/total)

indx = np.arange(1, len(immi) + 1)
benford = [np.log10(1 + (1.0 / d)) for d in indx]

plt.bar(indx, benford, width, color='r', label="Benford's Law")
plt.bar(np.arange(1, immi.shape[0]+1)+ width, 
                immi.immi_scaled, width, color='b', label="Predicted data")
# center the xtick labels
ax = plt.gca()
ax.set_xticks(indx + width / 2)
ax.set_xticklabels((indx))

# limit the  number of bars if you have more data
plt.xlim(1, 9)
plt.title("Immigrants in countries")
plt.ylabel("Probability")
plt.grid(True)
plt.legend()
plt.show()

【讨论】:

  • Traceback (most recent call last): File "/Users/MarcleSparkle/PycharmProjects/01-bendfords_law/test.py", line 18, in &lt;module&gt; immi.num_immigrants=immi.num_immigrants.str.replace(',', '').apply(float) File "/Users/MarcleSparkle/anaconda/lib/python3.5/site-packages/pandas/core/series.py", line 2220, in apply mapped = lib.map_infer(values, f, convert=convert_dtype) File "pandas/src/inference.pyx", line 1088, in pandas.lib.map_infer (pandas/lib.c:62658) ValueError: could not convert string to float: 'Number of immigrants'
  • 我收到NameError: name 'total' is not defined
  • 抱歉代码有问题@Marc 我刚刚做了一些更改并运行了代码,它现在可以工作了。
  • 如此接近!现在是ValueError: incompatible sizes: argument 'height' must be length 228 or scalar
  • 你快到了!我使用您在问题中提供的示例构建了这个示例。我不知道该错误的确切来源。完整的堆栈跟踪是什么?
【解决方案2】:

读取数据:

import locale

with open("immigrants.csv", newline='') as csvfile:
    immidata = csv.reader(csvfile)  # defaults are fine!
    X_labels = []
    Y = []
    for row in immidata:
        X_labels.append(row[0])
        Y.append(locale.atoi(row[1]))

为您提供 X_labelsY(转换为 int)。
注意:不需要close() with 块会自动执行此操作。

祝你好运。顺便说一句:digits 在您共享的代码中未定义 - 您应该尽一切努力使其成为 MCVE

【讨论】:

  • 谢谢!出于某种原因,它告诉我“未定义阅读器”是一个错误。
  • 是的,当然。感谢您的帮助!但是,出于某种奇怪的原因,我在 OP 中发布了一个奇怪的错误。
  • 看起来您的示例数据中没有显示标题行,请查看csv.dictreader
  • 啊,我明白了。将 'csv.reader' 更改为 'csv.DictReader' 的奇怪之处在于给了我'Traceback(最近一次调用最后):文件“/Users/MarcleSparkle/PycharmProjects/01-bendfords_law/benford.py”,第 17 行,在 X_labels.append(row[0]) KeyError: 0'
  • DictReader 使用列名而不是索引。
猜你喜欢
  • 2013-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-03
相关资源
最近更新 更多