CDF累积分布函数错误

2 投票
1 回答
1272 浏览
提问于 2025-04-21 03:14

我正在尝试为一个多列数据文件中的某一列绘制累积分布函数(CDF)。当数据文件中只有一列时,绘图效果很好。但是,当我试图从数据中提取特定列时,就出现了错误。我也尝试使用循环来读取特定列,读取是没问题的。如果我把绘图的代码放在循环外面,图表只显示了该列的最后一个值;而如果把绘图的代码放在循环里面,就会出现错误。这个问题不是出在读取文件或特定列上,也不是缩进的问题。我该如何解决这个问题呢?

带有循环的代码

import numpy as np
import matplotlib.pyplot as plt
from pylab import*
import math
from matplotlib.ticker import LogLocator

with open('input.txt', 'r') as f:
    for rows in f:
        cols = rows.split()
        data = cols[2]
        sorted_data = np.sort(data)
        cdf = np.arange(len(data))/float(len(data))
        plt.plot(sorted_data, cdf, '-bs')

plt.show()
#print data

错误信息

Traceback (most recent call last):
  File "cdf_plot.py", line 13, in <module>
    plt.plot(sorted_data, cdf, '-bs')
  File "/usr/lib/pymodules/python2.7/matplotlib/pyplot.py", line 2467, in plot
    ret = ax.plot(*args, **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 3893, in plot
    for line in self._get_lines(*args, **kwargs):
  File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 322, in _grab_next_args
    for seg in self._plot_args(remaining, kwargs):
  File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 300, in _plot_args
    x, y = self._xy_from_xy(x, y)
  File "/usr/lib/pymodules/python2.7/matplotlib/axes.py", line 240, in _xy_from_xy
    raise ValueError("x and y must have same first dimension")
ValueError: x and y must have same first dimension

没有循环的代码:

import numpy as np
import matplotlib.pyplot as plt
from pylab import*
import math
from matplotlib.ticker import LogLocator

data = np.loadtxt('input.txt')
data_one = [row[2] for row in data]
sorted_data = np.sort(data)
cdf = np.arange(len(data_one))/float(len(data_one))
#cumulative = np.cumsum(data)
#ccdf = 1 - cdf

#plt.plot(data, sorted_data, 'r-*')
plt.plot(sorted_data, cdf, '-bs')

#plt.xlim([0,0.5])
plt.gca().set_xscale("log")
plt.gca().set_yscale("log")
plt.show()

错误信息:

Traceback (most recent call last):
  File "cum_graph.py", line 7, in <module>
    data = np.loadtxt('e_p_USC_30_days.txt')
  File "/usr/lib/python2.7/dist-packages/numpy/lib/npyio.py", line 804, in loadtxt
    X = np.array(X, dtype)
ValueError: setting an array element with a sequence.

输入文件:我只对计算第3列(col[2])的CDF感兴趣

4814  2464  27  0.000627707861971  117923.0
4211  736  2  4.64968786645  05  2576.0
2075  1339  30  0.000697453179968  499822.0
2441  2381  3  6.97453179968  05  1968.0
4694  1738  1  2.32484393323  05  5702.0
4406  3008  12  0.000278981271987  8483.0
3622  1396  3  6.97453179968  05  2564.0
5425  478  1  2.32484393323  05  428.0
4489  1715  6  0.000139490635994  19045.0
3695  3387  2  4.64968786645  05  16195.0

1 个回答

4

这里有很多问题。

1 - 数据的问题

仔细看看你的数据:

4814  2464  27  0.000627707861971  117923.0
4211  736  2  4.64968786645  05  2576.0
2075  1339  30  0.000697453179968  499822.0
2441  2381  3  6.97453179968  05  1968.0
4694  1738  1  2.32484393323  05  5702.0
4406  3008  12  0.000278981271987  8483.0
3622  1396  3  6.97453179968  05  2564.0
5425  478  1  2.32484393323  05  428.0
4489  1715  6  0.000139490635994  19045.0
3695  3387  2  4.64968786645  05  16195.0

有时候你会看到6列数据,比如:

4211  736  2  4.64968786645  05  2576.0

而有时候你只有5列:

4814  2464  27  0.000627707861971  117923.0

所以第一步就是要学会正确地写数据。

2 - 正确写数据

想象一下,你的所有数据都在一个叫 data 的二维数组里。

你可以这样调用:

numpy.savetxt("input.txt", data)

或者,为了更好地控制格式:

numpy.savetxt("input.txt", data, fmt="%d %d %d %.6f %d %.1f")

这里的 fmt= 参数是告诉 numpy 你想怎么保存数据的方式(%d 表示以整数形式写,%f 表示以浮点数形式写,%.5f 表示以浮点数形式写,保留5位小数)。

如果你想自己写,可以这样做:

fmt = "%d %d %d %.6f %d %.1f"
with open("input.txt", "w") as f:
    for row in data:
        f.write(fmt%row+"\n")

如果你确实想写的是只有5列的行,那就用其他分隔符,比如 ,。这样,

4814,2464,27,0.000627707861971,,117923.0

显然包含了6列。

3 - 加载有效数据

我所说的有效数据是指一致的数据,也就是每行数据的列数总是相同。

你应该使用 numpy.loadtxtnumpy.genfromtxt(后者用于处理缺失数据)。注意,你可以为这两个函数指定分隔符,使用 delimiter 参数。

data = numpy.loadtxt("valid_input.txt")
col = data[:,2]

或者你也可以使用 usecols 参数和 unpack 参数一起使用。

4 - 加载无效数据

对于你的数据,使用 usecols 方法是有效的,只要你选择第三列(在 Python 中是第2列),前面没有其他错误。

你可以手动处理,这就引出了另一个问题:

5 - 你第一次实现的问题

在这里,你只是用一个单一的值替换了变量 data(即 cols[2] 的值):

with open('input.txt', 'r') as f:
    for rows in f:
        cols = rows.split()
        data = cols[2]

这里你试图对一个单一的值进行排序:

        sorted_data = np.sort(data)

这里你想获取一个单一值的长度:

        cdf = np.arange(len(data))/float(len(data))
        plt.plot(sorted_data, cdf, '-bs')

plt.show()

我真的很惊讶 numpy 没有报错。

你是逐行获取数据的:你需要把这些值存储到某个地方(比如一个列表)然后再处理它们。

6 - 你第二次实现的问题

numpy.loadtxt 无法加载你的数据(默认情况下它会尝试加载所有数据),因为它无法判断你想用6列还是5列的数据。所以它唯一能做的就是失败。

7 - 你自己的问题

首先,不要生气:我说这些是为了帮助你进步。我并不是在评判你,只是在告诉你面对这种错误时应该怎么做,无论是简单的还是复杂的。

  1. 阅读错误信息。
  2. 尝试理解发生了什么。
  3. 在网上查找这些错误。
  4. 问别人。

问题在于你似乎只是复制粘贴了错误信息,而没有真正去看它们,也没有尝试去理解(但我可能错了,我不知道你的想法 :))。

但可以肯定的是,你没有把这些错误信息放到你喜欢的搜索引擎里,因为网上有很多答案。同样,我可能错了。也许你确实这样做了,但没有看到这些答案如何适用于你的情况。不过,谷歌上关于

ValueError: x and y must have same first dimension

的第一个答案是非常明确的。你甚至不需要提到这是 matplotlib 或 Python。然后你就会发现 sorted_data 的长度和 cdf 不一样。再多花点时间,你就会明白我之前说的关于你实现的内容。

8 - 证明我错了

正如你所看到的,我没有给出一个“标准答案”,也不会给出,因为我认为你没有尽到自己的责任。但你仍然可以做到:我给了你所有需要的工具来回答你自己的问题。这并不意味着你要独自一人在一个孤岛上完成:我几乎给出了完整的答案(真的),文档也能帮到你,谷歌也是 :)。你所要做的就是稍微搜索一下。一旦你有了可用的东西,编辑你的问题(或者回答你自己的问题)。

撰写回答