9

我需要以秒为单位读取带有时间戳的长文件,并使用 numpy 或 scipy 绘制 CDF。我确实尝试过 numpy 但似乎输出不是它应该是的。下面的代码:任何建议表示赞赏。

import numpy as np
import matplotlib.pyplot as plt

data = np.loadtxt('Filename.txt')
sorted_data = np.sort(data)
cumulative = np.cumsum(sorted_data)

plt.plot(cumulative)
plt.show()
4

6 回答 6

19

你有两个选择:

1:可以先bin数据。这可以通过以下numpy.histogram功能轻松完成:

将 numpy 导入为 np
将 matplotlib.pyplot 导入为 plt

数据 = np.loadtxt('文件名.txt')

# 在这里选择你想要多少个垃圾箱
num_bins = 20

# 使用直方图函数对数据进行分箱
计数,bin_edges = np.histogram(数据,bins=num_bins,normed=True)

# 现在找到 cdf
cdf = np.cumsum(计数)

# 最后绘制 cdf
plt.plot(bin_edges[1:], cdf)

plt.show()

2:而不是使用numpy.cumsum,只需根据小于数组中每个元素的项目数绘制sorted_data数组(有关更多详细信息,请参阅此答案https://stackoverflow.com/a/11692365/588071):

将 numpy 导入为 np

将 matplotlib.pyplot 导入为 plt

数据 = np.loadtxt('文件名.txt')

sorted_data = np.sort(数据)

yvals=np.arange(len(sorted_data))/float(len(sorted_data)-1)

plt.plot(sorted_data,yvals)

plt.show()

于 2014-07-04T14:52:26.633 回答
7

为了完整起见,您还应该考虑:

  • 重复:您的数据中可能有多次相同的点。
  • 点之间可以有不同的距离
  • 点可以是浮动的

您可以使用numpy.histogram, 设置 bin 边缘,使每个 bin 只收集一个点的所有出现。您应该保留density=False,因为根据文档:

请注意,直方图值的总和将不等于 1,除非选择了统一宽度的 bin

您可以将每个 bin 中的元素数量除以数据大小进行标准化。

import numpy as np
import matplotlib.pyplot as plt

def cdf(data):

    data_size=len(data)

    # Set bins edges
    data_set=sorted(set(data))
    bins=np.append(data_set, data_set[-1]+1)

    # Use the histogram function to bin the data
    counts, bin_edges = np.histogram(data, bins=bins, density=False)

    counts=counts.astype(float)/data_size

    # Find the cdf
    cdf = np.cumsum(counts)

    # Plot the cdf
    plt.plot(bin_edges[0:-1], cdf,linestyle='--', marker="o", color='b')
    plt.ylim((0,1))
    plt.ylabel("CDF")
    plt.grid(True)

    plt.show()

例如,使用以下数据:

#[ 0.   0.   0.1  0.1  0.2  0.2  0.3  0.3  0.4  0.4  0.6  0.8  1.   1.2]
data = np.concatenate((np.arange(0,0.5,0.1),np.arange(0.6,1.4,0.2),np.arange(0,0.5,0.1)))
cdf(data)

你会得到:

CDF


您还可以对 cdf 进行插值以获得连续函数(使用线性插值或三次样条):

import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import interp1d

def cdf(data):

    data_size=len(data)

    # Set bins edges
    data_set=sorted(set(data))
    bins=np.append(data_set, data_set[-1]+1)

    # Use the histogram function to bin the data
    counts, bin_edges = np.histogram(data, bins=bins, density=False)

    counts=counts.astype(float)/data_size

    # Find the cdf
    cdf = np.cumsum(counts)

    x = bin_edges[0:-1]
    y = cdf

    f = interp1d(x, y)
    f2 = interp1d(x, y, kind='cubic')

    xnew = np.linspace(0, max(x), num=1000, endpoint=True)

    # Plot the cdf
    plt.plot(x, y, 'o', xnew, f(xnew), '-', xnew, f2(xnew), '--')
    plt.legend(['data', 'linear', 'cubic'], loc='best')
    plt.title("Interpolation")
    plt.ylim((0,1))
    plt.ylabel("CDF")
    plt.grid(True)

    plt.show()

插值

于 2016-05-16T12:58:08.817 回答
2

作为一个快速的答案,

plt.plot(sorted_data, np.linspace(0,1,sorted_data.size)

应该得到你想要的

于 2015-04-08T09:04:04.127 回答
2

以下是我的实施步骤:

1.排序你的数据

2.计算每个'x'的累积概率

import numpy as np
import matplotlib.pyplab as plt

def cdf(data):
    n = len(data)
    x = np.sort(data) # sort your data
    y = np.arange(1, n + 1) / n # calculate cumulative probability
    return x, y

x_data, y_data = cdf(your_data)
plt.plot(x_data, y_data) 

例子:

test_data = np.random.normal(size= 100)
x_data, y_data = ecdf(test_data)
plt.plot(x_data, y_data, marker= '.', linestyle= 'none')

图:图 的链接

于 2017-08-27T14:28:15.710 回答
1

如果有许多重复值(因为我们只需要对唯一值进行排序),这里的实现会更有效。并且它将 CDF 绘制为阶跃函数,严格来说就是这样。

import sys

import numpy as np
import matplotlib.pyplot as plt

from collections import Counter


def read_data(fp):
    t = []
    for line in fp:
        x = float(line.rstrip())
        t.append(x)
    return t


def main(script, filename=None):
    if filename is None:
        fp = sys.stdin
    else:
        fp = open(filename)

    t = read_data(fp)
    counter = Counter(t)

    xs = counter.keys()
    xs.sort()

    ys = np.cumsum(counter.values()).astype(float)
    ys /= ys[-1]

    options = dict(linewidth=3, alpha=0.5)
    plt.step(xs, ys, where='post', **options)
    plt.xlabel('Values')
    plt.ylabel('CDF')
    plt.show()


if __name__ == '__main__':
    main(*sys.argv)
于 2016-12-22T16:14:14.297 回答
0

如果您想可以使用 seaborn 库,请执行以下操作:

import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
data = pd.read_csv('Filename.txt', sep=" ", header=None)
plt.figure()
sns.kdeplot(data,cumulative=True)
plt.show()
于 2019-03-17T18:00:39.047 回答