读取并绘制实时实时自我更新 csv 文件

Posted

技术标签:

【中文标题】读取并绘制实时实时自我更新 csv 文件【英文标题】:Read and plot real time live self updating csv file 【发布时间】:2018-05-22 09:12:39 【问题描述】:

所以,我有一个可自行更新的 .csv 文件。我想用它做一些事情,不知道如何处理它,希望你能帮助我。 csv 中的数据如下所示: 没有标题。我也可以在没有分隔符的情况下将日期和时间加入同一列。

07/12/2017,23:50,113.179,113.182,113.168,113.180,113.187,113.189,113.176,113.186,144
07/12/2017,23:51,113.180,113.190,113.180,113.187,113.186,113.196,113.186,113.193,175
07/12/2017,23:52,113.187,113.188,113.174,113.186,113.193,113.194,113.181,113.192,340
07/12/2017,23:53,113.186,113.192,113.175,113.181,113.192,113.199,113.182,113.188,282
07/12/2017,23:54,113.181,113.183,113.170,113.171,113.188,113.188,113.176,113.179,74
07/12/2017,23:55,113.171,113.181,113.170,113.179,113.179,113.188,113.176,113.186,329
07/12/2017,23:56,113.179,113.189,113.174,113.181,113.186,113.195,113.181,113.187,148
07/12/2017,23:57,113.181,113.181,113.169,113.169,113.187,113.187,113.175,113.175,55
07/12/2017,23:58,113.169,113.183,113.169,113.182,113.175,113.188,113.175,113.187,246
07/12/2017,23:59,113.182,113.210,113.175,113.203,113.187,113.215,113.181,113.209,378
08/12/2017,00:00,113.203,113.213,113.180,113.183,113.209,113.220,113.187,113.190,651
08/12/2017,00:01,113.183,113.190,113.164,113.167,113.190,113.196,113.171,113.174,333
08/12/2017,00:02,113.167,113.182,113.156,113.156,113.174,113.188,113.162,113.163,265
08/12/2017,00:03,113.156,113.165,113.151,113.163,113.163,113.172,113.158,113.170,222
08/12/2017,00:04,113.163,113.163,113.154,113.159,113.170,113.170,113.159,113.166,148
08/12/2017,00:05,113.159,113.163,113.153,113.154,113.166,113.168,113.159,113.162,162

对于初学者,我有兴趣在此练习中仅使用前两列(如果日期和时间分开,则使用前两列)。比如:

07/12/2017,21:54,113.098
07/12/2017,21:55,113.096
07/12/2017,21:56,113.087
07/12/2017,21:57,113.075
07/12/2017,21:58,113.087
07/12/2017,21:59,113.079

每隔一秒左右就会添加新的行,其中包含更新的日期时间。 我可以做类似的事情

df = pd.read_csv("C:\\Users\\xxx\\Desktop\\csvexport\\thefile.csv")
print(df[-1:])

查看数据帧的最后一行(尾部)

现在,我无法执行以下操作,感谢您的帮助:

    更新数据框,以便我可以使用最新版本来计算新行何时出现(不使用睡眠计时器?)

    能够绘制数据,新数据到达时会自动反映新更新的数据(x 轴上的日期时间,y 轴上的浮点数)

我在生成 .csv 文件的程序的命令窗口中看到的输出是这样的,如果这很重要的话

asset 08/12/2017 05:16:37 float:113.336 floattwo:113.328 digit:20
asset 08/12/2017 05:16:40 float:113.334 floattwo:113.328 digit:21
asset 08/12/2017 05:16:40 float:113.335 floattwo:113.323 digit:22
asset 08/12/2017 05:16:41 float:113.331 floattwo:113.328 digit:23
asset 08/12/2017 05:16:43 float:113.334 floattwo:113.327 digit:24
asset 08/12/2017 05:16:47 float:113.332 floattwo:113.328 digit:25

因此您可以看到更新并不完全相隔一秒,它们可能存在间隙,有时也可能在同一秒内发生(05:16:40 两次)

因此,我希望将情节保持在相同的时间间隔(1 分钟或 5 分钟等),但根据属于该分钟的 .csv 中的浮动值不断更改最近的点.当下一分钟的一行到达时,只有这样情节才能向右移动(但随着浮点数的变化而不断波动)......希望你明白这一点。我想用 pyqtgraph 作图。

我设法编写了这么多代码......但这不是最好的例子,对不起。当然,情节并不是这样的。只是说明我想看到的。所以绿条应该不断改变值,直到下一个时间步被添加到 csv

import pyqtgraph as pg
from pyqtgraph import QtCore, QtGui
import pandas as pd
import datetime

x = pd.read_csv("C:\\Users\\xxx\\Desktop\\csvexport\\thefile.csv")
z = x[-1:]

def getlastrow():
    for a in z.iterrows():
        d = ((int(((a[1][0]).split("/")[0]))))
        m = ((int(((a[1][0]).split("/")[1]))))
        y = ((int(((a[1][0]).split("/")[2]))))        
        hh = ((int(((a[1][1]).split(":")[0]))))
        mm = ((int(((a[1][1]).split(":")[1]))))
        #ss = ((int(((a[1][1]).split(":")[2]))))        
        thedate = datetime.date(y, m, d)
        thetime = datetime.time(hh, mm)
        p = (a[1][2])
        return ((thedate,thetime,p))

# print(str(getlastrow()[0]).replace("-",""))
# print(getlastrow()[1])
# print(getlastrow()[2])

class CandlestickItem(pg.GraphicsObject):
    def __init__(self):
        pg.GraphicsObject.__init__(self)
        self.flagHasData = False

    def set_data(self, data):
        self.data = data
        self.flagHasData = True
        self.generatePicture()
        self.informViewBoundsChanged()

    def generatePicture(self):
        self.picture = QtGui.QPicture()
        p = QtGui.QPainter(self.picture)
        p.setPen(pg.mkPen('w'))
        w = (self.data[1][0] - self.data[0][0]) / 2.
        for (t, open) in self.data:
            p.drawLine(QtCore.QPointF(t, open), QtCore.QPointF(t, open))
            p.setBrush(pg.mkBrush('r'))
            if open > 122.8:
                p.setBrush(pg.mkBrush('g'))
            p.drawRect(QtCore.QRectF(t-w, open, w*2, open))
        p.end()

    def paint(self, p, *args):
        if self.flagHasData:
            p.drawPicture(0, 0, self.picture)

    def boundingRect(self):
        return QtCore.QRectF(self.picture.boundingRect())

app = QtGui.QApplication([])

data = [
    [(int(str(getlastrow()[0]).replace("-",""))), (getlastrow()[2])],
    [(int(str(getlastrow()[0]).replace("-","")))+1, (getlastrow()[2])+0.1],
    [(int(str(getlastrow()[0]).replace("-","")))+2, (getlastrow()[2])+0.2],
]
item = CandlestickItem()
item.set_data(data)
plt = pg.plot()
plt.addItem(item)
plt.setWindowTitle('pyqtgraph example: customGraphicsItem')

def update():
    global item, data
    new_bar = (int(str(getlastrow()[0]).replace("-","")))+3, ((getlastrow()[2])+10)
    data.append(new_bar)
    item.set_data(data)
    app.processEvents()

timer = QtCore.QTimer()
timer.timeout.connect(update)
timer.start(100)

if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()  

【问题讨论】:

为什么要把它写到平面文件中?而是使用数据库 哦,这是另一天的大话题。我正在读这个。 quant.stackexchange.com/questions/29572/… 不,这不是写入和使用数据的方式。与平面文件相比,数据库提供了更多功能。 同时我会尝试从matthewrocklin.com/blog/work/2017/10/16/streaming-dataframes-1获得一些灵感 这可以成为解决方案之一 【参考方案1】:

希望下面的代码对第 (1) 点有所帮助。我意识到这是部分答案。我使用 Linux 进行了测试。代码应该与操作系统无关,但我尚未对此进行测试。

代码使用看门狗库监视 TEST_DIR 中定义的目录。如果在 TEST_FILE 中定义的文件发生更改,则从名为 MyHandler 的事件处理类向主函数发送一条消息。我进行了一些难看的时间检查,因为每次更改文件时都会触发多个事件。因此,对于在 THRESHOLD 时间内发生的事件,只会触发一次调度。我将其设置为 0.01 秒。

向 dispatcher_receiver 函数添加代码以读入更新的文件。

import ntpath
# pip3 install pydispatcher --user
from pydispatch import dispatcher
import sys
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler


MYHANDLER_SENDER = 'myhandler_sender'
MYHANDLER_SIGNAL = 'myhandler_signal'
TEST_FILE = 'test_data.csv'
TEST_DIR = '/home/bill/data/documents/infolab2/progs/jupyter_notebooks/pyqtgraph/test_data/'
THRESHOLD_TIME = 0.01


class MyHandler(FileSystemEventHandler):
    ''' handle events from the file system '''
    def __init__(self):
        self.start_time = time.time()

    def on_modified(self, event):
        now_time = time.time()
        # filter out multiple modified events occuring for a single file operation
        if (now_time - self.start_time) < THRESHOLD_TIME:
            print('repeated event, not triggering')
            return
        changed_file = ntpath.basename(event.src_path)
        if changed_file == TEST_FILE:
            print('changed file: '.format(changed_file))
            print('event type: '.format(event.event_type))
            print('do something...')
            # print(event)
            message = ' changed'.format(changed_file)
            dispatcher.send(message=message, signal=MYHANDLER_SIGNAL, sender=MYHANDLER_SENDER)
        self.start_time = now_time


def main():
    dispatcher.connect(dispatcher_receive, signal=MYHANDLER_SIGNAL, sender=MYHANDLER_SENDER)
    observer = Observer()
    observer.schedule(event_handler, path=TEST_DIR, recursive=False)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

def dispatcher_receive(message):
    print('received dispatch: '.format(message))
    # read in the altered file

if __name__ == "__main__":
    event_handler = MyHandler()
    main()

【讨论】:

感谢您的建议。我在保存文件等时看到代码有效,但我注意到我的自我更新 csv 的工作方式是它不会在每次更改时都对其进行修改。当我打开文件时,我可以看到最后一行的值发生了变化,但是当右键单击文件并转到属性时,修改日期没有改变,所以我认为更新文件的程序只是进行更改而不是保存它。有没有办法让你的代码适应 pandas 数据框来读取 csv 的最后一行,看看它是否是新行,而不是 .csv。因为我可以在 pandas df 中打开 csv 并访问新值 尝试在两行中将 FileSystemEventHandler 更改为 LoggingEventHandler:from watchdog.events import FileSystemEventHandler 和 class MyHandler(FileSystemEventHandler):

以上是关于读取并绘制实时实时自我更新 csv 文件的主要内容,如果未能解决你的问题,请参考以下文章

使用 Python 实时读取 txt 文件并更新 postgresql 数据库

你可以在 matplotlib 中绘制实时数据吗?

两个程序可以同时更新一个文本文件(实时通信)吗?

读取文件夹中的所有 .csv 文件并绘制其内容

Apache Hudi 数据湖概述

Apache Hudi 数据湖概述