【问题标题】:Plotting with matplotlib: TypeError: float() argument must be a string or a number使用 matplotlib 绘图:TypeError:float() 参数必须是字符串或数字
【发布时间】:2018-06-24 14:33:02
【问题描述】:

在寻找我的previous question 的解决方案时(显然已经解决了),我遇到了另一个尚未解决的问题。我会非常感谢任何可以帮助我解决它的人!

有人认为我使用的是 matplotlib 1.5.1 的过时版本,但我现在已将其更新到 2.1.1 以及 numpy 到 1.14.0,这对我没有帮助,唉。

所以,再一次。我有一个 CSV 文件作为输入:

16,59,55,51 13.8
17,00,17,27 13.7
17,00,39,01 13.6
17,01,01,06 13.4

我在上面运行这个 python 脚本:

import matplotlib.pyplot as plt
import csv
from datetime import time

x = []
y = []

with open('calibrated.csv','r') as csvfile:
    plots = csv.reader(csvfile, delimiter=' ')
    for row in plots:
        hours,minutes,seconds,milliseconds = [int(s) for s in row[0].split(",")]

        x.append(time(hours,minutes,seconds,milliseconds))
        y.append(float(row[1]))

plt.plot(x,y, marker='o', label='brightness')
plt.gca().invert_yaxis()
plt.xlabel('time [UT]')
plt.ylabel('brightness [mag, CR]')
plt.legend()
plt.grid()
plt.show()

我得到了这个 TypeError (而解决我之前问题的人没有它!):

Traceback (most recent call last):
  File "lightcurve.py", line 16, in <module>
    plt.plot(x,y, marker='o', label='brightness')
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/pyplot.py", line 3154, in plot
    ret = ax.plot(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/__init__.py", line 1812, in inner
    return func(ax, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/axes/_axes.py", line 1425, in plot
    self.add_line(line)
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.py", line 1708, in add_line
    self._update_line_limits(line)
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/axes/_base.py", line 1730, in _update_line_limits
    path = line.get_path()
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/lines.py", line 925, in get_path
    self.recache()
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/lines.py", line 612, in recache
    x = np.asarray(xconv, np.float_)
  File "/usr/local/lib/python2.7/dist-packages/numpy/core/numeric.py", line 531, in asarray
    return array(a, dtype, copy=False, order=order)
TypeError: float() argument must be a string or a number

我被困在那里了。

【问题讨论】:

  • 可以确认我没有看到这个错误...
  • 如果你使用 matplotlib 和 numpy,然后跳转并使用 pandas。
  • 嗯。你能显示print(x[0])print(type(x[0]))吗?
  • 问题中的代码对我来说也确实运行良好。我猜想,虽然每个人都在查看问题中的四行 csv 文件,但这实际上并不是您遇到问题的文件。所以首先尝试使用 4-line-file 并查看这是否会产生错误(我强烈怀疑它,因为其中没有任何内容,这会导致您得到错误)。然后找出实际文件中的哪些行产生错误并显示问题中的那些行的副本。
  • 有趣的是@cᴏʟᴅsᴘᴇᴇᴅ 从一开始就建议使用 pandas 是完全正确的,只是以一种非常不同的方式。 ;-)

标签: python numpy matplotlib typeerror


【解决方案1】:

ma​​tplotlib 有一个名为 plot_date 的内置函数,可以帮助您。请注意,您的时间序列必须采用日期时间格式(尽管您可以任意添加年、月和日,因为如果所有时间都在同一天,它们不会影响绘图)。

代码如下:

import matplotlib.pyplot as plt
import csv
import datetime

x = []
y = []

with open('calibrated.csv','r') as csvfile:
    plots = csv.reader(csvfile, delimiter=' ')
    year = 2017
    month = 1
    day = 16
    for row in plots:
        hours,minutes,seconds,milliseconds = [int(s) for s in row[0].split(",")]

        x.append(datetime.datetime(year,month,day,hours,minutes,seconds,milliseconds))
        y.append(float(row[1]))


plt.plot_date(x,y, marker='o', label='brightness')
plt.gca().invert_yaxis()
plt.xlabel('time [UT]')
plt.ylabel('brightness [mag, CR]')
plt.legend()
plt.grid()
plt.show()

正如coldspeed 指出的那样,您可能会从使用pandas 中受益匪浅。

请注意,现在如果时间序列更长,情节仍然可以正常工作。

感谢@ImportanceOfBeingErnest 指出最初的误解。

【讨论】:

  • 您在此处生成分类图。第一类是16:59:55.000051,第二类是17:00:17.000027 等。这些类别是等间距的,而不是根据数字日期的间距。这肯定是不希望的。此外,如果您有 100 个数据点,您最终会在图上得到 100 个类别。这看起来就像来自this question 的情节。
  • @Robbie 您的解决方案确实有效,谢谢您!但我仍然想知道为什么我的 python 脚本适用于其他人,但不适用于我。 :)
  • 你是对的@ImportanceOfBeingErnest,现在正在编辑。感谢您指出这一点。
  • plotplot_date 之间应该没有任何区别。 plot_date 本质上唯一要做的就是自动将刻度定位器和格式化程序设置为用于日期的那些。这在将数字插入plot_date 函数时很有用。对于 datetime 对象,plotplot_date 的工作方式相同。这显然有效的原因是您使用 year,month,daydatetime 对象,而不是 datetime.time 对象。
【解决方案2】:

使用 matplotlib 2.1 和 numpy 1.13,问题中的代码可以正常工作。

为什么大多数人能够无错误地运行代码的一个合理解释可能是 matplotlib 将依赖 pandas 来绘制 datetime.time 对象。如果未安装或找不到 pandas,它将因此失败。

代码中隐含了一些假设,这可能会导致出现的问题和错误。这是单独的时间可能无法在 matplotlib 轴上很好地表示,这通常会期望日期时间(即包括日期)对象。

在坐标轴上引入一些日期可能会解决问题。

import io

u = u"""16,59,55,51 13.8
17,00,17,27 13.7
17,00,39,01 13.6
17,01,01,06 13.4"""

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import csv
from datetime import datetime

x = []
y = []

plots = csv.reader(io.StringIO(u), delimiter=' ')
for row in plots:
    hours,minutes,seconds,milliseconds = [int(s) for s in row[0].split(",")]

    x.append(datetime(2018,1,1,hours,minutes,seconds,milliseconds))
    y.append(float(row[1]))

plt.plot(x,y, marker='o', label='brightness')
plt.gca().invert_yaxis()
plt.xlabel('time [UT]')
plt.ylabel('brightness [mag, CR]')
plt.legend()
plt.grid()

hours = mdates.SecondLocator(bysecond=[0,30])
t_fmt = mdates.DateFormatter('%H:%M:%S')
plt.gca().xaxis.set_major_locator(hours)
plt.gca().xaxis.set_major_formatter(t_fmt)

plt.show()

【讨论】:

  • @ImportanceOfBeingErnest 如果我将 matplotlib 回滚到 2.1 会怎样?我以前从未这样做过,不确定我是否真的应该出于测试目的尝试这样做?
  • FWIW,我使用的是 Python 2.7 和 matplotlib 2.1.1,问题中的代码对我来说很好。
  • @ImportanceOfBeingErnest 是的,这似乎是问题所在。卸载熊猫会为我重现错误
  • @SergiusPro 好吧,pandas >0.20.1 还有一个问题,那就是它不再自动注册转换器。因此,出于这个原因,人们可能会认为这不适用于任何 >0.20.1 的熊猫。一个解决方案将是来自this question
  • @ImportanceOfBeingErnest 是的!就是这个!现在我原来的 python 脚本产生了它应该的东西。啊,我们终于明白了。感谢所有参与者! :)
猜你喜欢
  • 2018-08-31
  • 2019-05-14
  • 2022-01-09
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-21
相关资源
最近更新 更多