Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从CSV导入时间序列并使用Python绘制图形的最佳方法_Python_Perl - Fatal编程技术网

从CSV导入时间序列并使用Python绘制图形的最佳方法

从CSV导入时间序列并使用Python绘制图形的最佳方法,python,perl,Python,Perl,我必须多次执行的一项任务是读取包含一些时间序列数据的CSV文件,然后绘制一个显示所有数据的图表 我必须从CSV文件导入数据。它可能没有排序,可能有间隙,每个系列可以在不同的日期开始和结束。例如: Employee;Year;Salary Mark;2014;29000 Paul;2013;33000 Paul;2014;34000 Mark;2011;20000 Mark;2012;24000 Mark;2015;30000 我想把它全部放在一个图表中,显示每个时间序列(两行,其中X轴是日期,

我必须多次执行的一项任务是读取包含一些时间序列数据的CSV文件,然后绘制一个显示所有数据的图表

我必须从CSV文件导入数据。它可能没有排序,可能有间隙,每个系列可以在不同的日期开始和结束。例如:

Employee;Year;Salary
Mark;2014;29000
Paul;2013;33000
Paul;2014;34000
Mark;2011;20000
Mark;2012;24000
Mark;2015;30000
我想把它全部放在一个图表中,显示每个时间序列(两行,其中X轴是日期,Y轴是员工的工资)。关键是要考虑到数据中存在的任何差距

好的,我开始学习用Perl编程。我解决这个问题的第一个方法是:

首先,从CSV导入数据并将其存储到哈希中,如下所示:

$imported_data->{$employee}{$year} = $salary;
[ 2011, 2012, 2013, 2014, 2015 ]
导入数据后,我使用循环和DateTime模块生成一系列无间隙的排序日期。它将产生如下数组:

$imported_data->{$employee}{$year} = $salary;
[ 2011, 2012, 2013, 2014, 2015 ]
然后,我为每个员工生成工资数据数组。我使用日期数组进行循环,查找每个日期的工资,如果数据缺失,则返回一个undef:

for my $date (@dates) {
    $salary = $imported_data->{$employee}{$year};
    if ( defined $salary ) {
        push @salary_array, $salary;
    } else {
        push @salary_array, undef;
    }
}
这将产生以下数组(每个员工一个):

现在我可以绘制数据,将日期数组(X值)与每个工资数组(Y值)配对,得到一个包含两个系列的XY图。数据现在已排序,间隙将正确显示

好的,我不知道这是否是最好的方法(可能不是…),但效果很好

然而,现在我开始使用Phyton,我想重新思考这种完成任务的方式。如您所见,在Perl中,我使用了散列来存储导入的数据。我不知道Phyton的字典是否能做到这一点,也不知道它是否易于管理


所以我愿意接受更有经验的程序员的想法。你会怎么做?对于这类事情有什么有用的模块吗?

因为你是python新手,我建议你看看
numpy
pandas
了解一般的数学和数据操作,看看
matplotlib
了解绘图

对于这个问题,一个可能的解决方案是:

from collections import defaultdict
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

data = [["Mark", 2014, 29000],
        ["Paul", 2013, 33000],
        ["Paul", 2014, 34000],
        ["Mark", 2011, 20000],
        ["Mark", 2012, 24000],
        ["Mark", 2015, 30000]]

data_csv = pd.DataFrame(data, columns=["Employee", "Year", "Salary"])


data_dict = defaultdict(list)

for row in data_csv.values:
        data_dict[row[0]].append(row[1:])


fig = plt.figure()
ax = plt.gca()


for name in data_dict.keys():
        data_dict[name] = np.concatenate(data_dict[name]).reshape(-1, 2)
        ax.scatter(data_dict[name][:,0], data_dict[name][:,1], label=name)

plt.legend()
plt.show()

在第一行中,我使用
pandas
创建了一个虚拟csv文件,而在您的示例中,您将使用
pd.read\u csv
加载它


核心是
defaultdict
:由于事先不知道员工的数量,字典的值被初始化为列表。然后我检查csv中的每一行,并将每个姓名(dict中的一个键)的年份和工资附加到列表中。此时,只需使用
numpy
重塑2d数组中的所有内容并绘制结果。

这里是另一个示例,使用
numpy
defaultdict
csv.reader()
,以及类:

from collections import defaultdict
import csv
import matplotlib.pyplot as plt
import numpy as np

def main():
    raw_data = FileReader(fn='salary.csv')
    data = ProcessData(raw_data)
    Plotter(data)

class ProcessData:
    def __init__(self, data):
        self.data = data
        self.t = sorted(data.years, key=int)
        self.names = sorted(list(data.salary.keys()))
        self.salary = dict()
        self.create_salary_data()

    def create_salary_data(self):
        for name in self.names:
            s = []
            for year in self.t:
                if year in self.data.salary[name]:
                    s.append(self.data.salary[name][year])
                else:
                    s.append(None)
            self.salary[name] = s

class FileReader:
    def __init__(self, **kwargs):
        if not 'fn' in kwargs:
            raise Exception('No file name given')
        self.fn = kwargs['fn']
        self.salary = defaultdict(lambda: defaultdict(float))
        self.years = set()
        self.read_file()

    def read_file(self):
        with open('salary.csv', newline='') as csvfile:
            reader = csv.reader(csvfile, delimiter=';')
            header = next(reader)
            for row in reader:
                if len(row)==0:
                    continue
                if len(row) != 3:
                    raise Exception('Bad row length in csv file')
                name, year, salary = row
                self.salary[name][year] = salary
                self.years.add(year)

class Plotter:
    def __init__(self, data):
        self.data = data
        t = data.t
        names = sorted(list(data.salary.keys()))
        fig, ax = plt.subplots()
        for name in names:
            temp = data.salary[name]
            s = list(map(lambda ss: np.nan if ss is None else float(ss), temp))
            ax.plot(t, s, label=name)

        ax.set(xlabel='Date (year)', ylabel='Salary (\$\$)',
           title='Employee salary')
        ax.grid()
        ax.legend(loc='upper right')
        plt.show()

main()