【问题标题】:How can I properly graph these two datasets using Pandas in Matplotlib?如何在 Matplotlib 中使用 Pandas 正确绘制这两个数据集?
【发布时间】:2022-01-25 17:50:55
【问题描述】:

我有两个数据集要相互绘制。

第一个数据集是狗狗币的每日价格。我正在使用 yfinance 和 mplfinance 来绘制图表。

第二个数据集是狗狗币钱包交易的 CSV 文件,其中有一列名为“余额”,显示交易时狗狗币钱包的余额。余额随着加密货币的进出而波动。以下是 CSV 供参考。

https://www.mediafire.com/file/x53x9bowjrrcook/DSb5CvAXhXnzFoxmiMaWpgxjDF6CfMK7h2.csv/file

我正在尝试将余额作为折线图,以显示余额的波动。

下面是我的代码。我试图用这段代码完成的是绘制狗狗币价格图表,然后将 CSV 中的余额绘制为折线图,并将图表相互叠加。当显示在图表上时,我试图让两个数据集中的日期相同,以便正确显示数据。

第一个问题是我一直无法弄清楚如何将这两个图表相互绘制。第一个图表来自 mplfinance,第二个图表来自 matplotlib。如果这两个模块不能相互绘制,那么我可以使用每日狗狗币价格的 csv 来代替 mplfinance 和 yfinance。

我遇到的第二个问题是我的余额图在余额减少时不会波动,只会增加。

import yfinance as yf 
import matplotlib
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd 
import mplfinance as mpf 

#This charts the Dogecoin Price 

df = yf.Ticker("DOGE-USD").history(period='max')

df = df.loc["2021-01-01":] 

mpf.plot(df, type="candle")


#This charts the balance from CSV

parse_dates = ['Time']
df = pd.read_csv('DSb5CvAXhXnzFoxmiMaWpgxjDF6CfMK7h2.csv', index_col=0, parse_dates=parse_dates)

plt.plot(df["Time"], df["Balance"])
plt.gca().invert_yaxis()
plt.show()

【问题讨论】:

  • @BigBen 由于格式问题,我无法将 CSV 数据放入文本中。更新了 CSV 的下载链接。感谢您的输入
  • 叠加图表很容易。您需要解决的第一个问题覆盖图表,而是“...让两个数据集中的日期相同,以便正确显示数据。 "一旦你这样做了,覆盖图表就很容易了,完全可以使用 mplfinance 使用 mpf.make_addplot()mpf.plot() 来完成。让我看一下数据,看看如何排列日期戳。
  • @DanielGoldfarb 我一直在试图弄清楚如何排列日期以使它们相同,但这是最难的部分。这是没有教程的事情之一。非常感谢任何帮助。

标签: python pandas matplotlib


【解决方案1】:

在您将两个数据集的时间戳对齐之前,必须先清理 csv 文件的许多问题。

这是 csv 文件在您阅读时的样子:

df = pd.read_csv('DSb5CvAXhXnzFoxmiMaWpgxjDF6CfMK7h2.csv', index_col=0, parse_dates=parse_dates)
时间金额余额余额,美元@价格利润 堵塞 4073636 2022-01-23 02:20:27 UTC 2022-01-23 02:20:27+00:00 +20,000 DOGE (2,707.16 USD) 2,740,510.04941789 DOGE $370,950 @ $0.135 $134,009 4063557 2022-01-15 14:37:15 UTC 2022-01-15 14:37:15+00:00 -676,245.18946621 DOGE (128,175.63 USD) 2,720,510.04941789 DOGE $515,6413 @ $0,19 $28 4014695 2021-12-10 14:24:11 UTC 2021-12-10 14:24:11+00:00 +129,967 DOGE (21,907.16 USD) 3,396,755.2388841 DOGE $572,555 @ $0.169 $210,146 4014652 2021-12-10 13:39:36 UTC 2021-12-10 13:39:36+00:00 +20,000 DOGE (3,466.9 USD) 3,266,788.2388841 DOGE $566,282 @ $0.173 $225,780 4014275 2021-12-10 06:56:33 UTC 2021-12-10 06:56:33+00:00 +1,980,000 DOGE (331,523.17 USD) 3,246,788.2388841 DOGE $543,629 @ $0.167 $206,594

关于此文件的一些注意事项:

  • 时间戳存在于 Time 列和 Block 列(您已设置为索引)中,但 block 列还包含其时间戳旁边的块编号。
  • 余额列包含单词“DOGE”,因此显然是一个字符串(不是浮点数)。
  • 其实所有这种方式从csv文件中读取的列,都是字符串(除了Time列,由于parse_dates)。

我建议,首先,只阅读 Time 和 Balance 列,并将 time 列设置为索引。同时,您可以将数据反转,使其按照从最早到最晚的时间顺序:

dfb = pd.read_csv('DSb5CvAXhXnzFoxmiMaWpgxjDF6CfMK7h2.csv',usecols=['Time','Balance'],index_col=0, parse_dates=True)
dfb = dfb.iloc[::-1]  # reverse the data
print(dfb.head(8))
平衡 时间 2021-04-24 10:20:22+00:00 47 狗 2021-04-24 10:34:39+00:00 57 狗 2021-04-24 10:40:49+00:00 67 狗 2021-04-24 10:42:22+00:00 58 狗 2021-04-24 10:50:46+00:00 49 狗 2021-04-26 09:48:52+00:00 19,049 狗 2021-04-26 13:39:54+00:00 49 狗 2021-04-26 16:22:06+00:00 20,099 狗

现在您可以通过将列字符串拆分为实际余额和单词“DOGE”来清理余额列,并将实际余额转换为浮点数:

dfb["Balance"] = dfb["Balance"].str.split(expand=True).iloc[:,0]  # [:,0] to take only balance and throw away "DOGE"
dfb["Balance"] = dfb["Balance"].str.replace(',','').astype(float) # remove commas from balance and convert to float.
print(dfb.head(16))
print(dfb.tail())
平衡 时间 2021-04-24 10:20:22+00:00 4.700000e+01 2021-04-24 10:34:39+00:00 5.700000e+01 2021-04-24 10:40:49+00:00 6.700000e+01 2021-04-24 10:42:22+00:00 5.800000e+01 2021-04-24 10:50:46+00:00 4.900000e+01 2021-04-26 09:48:52+00:00 1.904900e+04 2021-04-26 13:39:54+00:00 4.900000e+01 2021-04-26 16:22:06+00:00 2.009900e+04 2021-04-27 16:18:41+00:00 8.901000e+02 2021-04-29 15:37:30+00:00 2.500800e+04 2021-04-29 18:08:48+00:00 4.500800e+04 2021-04-29 18:21:54+00:00 7.999429e+04 2021-04-29 18:55:09+00:00 1.049685e+05 2021-04-30 02:48:24+00:00 8.049615e+05 2021-04-30 03:28:13+00:00 2.004911e+06 2021-04-30 04:36:35+00:00 1.985752e+06 平衡 时间 2021-12-10 06:56:33+00:00 3.246788e+06 2021-12-10 13:39:36+00:00 3.266788e+06 2021-12-10 14:24:11+00:00 3.396755e+06 2022-01-15 14:37:15+00:00 2.720510e+06 2022-01-23 02:20:27+00:00 2.740510e+06

现在看一下来自 yfinance 的数据,并将其与 csv 文件数据进行比较:

df = yf.Ticker("DOGE-USD").history(period='max')
df = df.loc["2021-01-01":] 
print(df.head(8))
print(df.tail())
开盘 高 低 收盘 成交量 红利 股票分割 日期 2021-01-01 0.004681 0.005685 0.004615 0.005685 228961515 0 0 2021-01-02 0.005686 0.013698 0.005584 0.010615 3421562680 0 0 2021-01-03 0.010602 0.013867 0.009409 0.009771 2707003608 0 0 2021-01-04 0.009785 0.011421 0.007878 0.009767 1372398979 0 0 2021-01-05 0.009767 0.010219 0.008972 0.009920 687256067 0 0 2021-01-06 0.009923 0.010854 0.009685 0.010465 749915516 0 0 2021-01-07 0.010454 0.010532 0.009162 0.009742 520644706 0 0 2021-01-08 0.009743 0.010285 0.008986 0.009846 394462164 0 0 开盘 高 低 收盘 成交量 红利 股票分割 日期 2022-01-22 0.142651 0.145027 0.122816 0.132892 1693524581 0 0 2022-01-23 0.132960 0.143072 0.132819 0.141863 1006234946 0 0 2022-01-24 0.141881 0.141951 0.127220 0.137798 1446873574 0 0 2022-01-25 0.137784 0.147236 0.133235 0.143049 1347567750 0 0 2022-01-26 0.142737 0.146615 0.142239 0.146615 1371126400 0 0

有几点需要注意:

  • yfinance 的数据每天只有一行
  • csv 数据有
    • 每天多行
    • 有些日子比其他日子有更多的行
    • 有些日子完全消失了

为了能够加入这两个数据集,我建议首先重新采样余额数据,以便您每天只有一行。我还建议这样做,每天的余额是该日期的最终余额。这可以使用 pandas 的 ohlc() (open,high,low,close) 聚合器来完成,然后将每天的“close”作为该日期的最终余额:

newdfb = dfb['Balance'].resample('D').ohlc().dropna()  # dropna gets rid of rows that have no data
newdfb.drop(['open','high','low'],axis=1,inplace=True) # keep only "close"
newdfb.columns = ['Balance']  # rename "close" to "Balance"
print(newdfb.head())
平衡 时间 2021-04-24 00:00:00+00:00 4.900000e+01 2021-04-26 00:00:00+00:00 2.009900e+04 2021-04-27 00:00:00+00:00 8.901000e+02 2021-04-29 00:00:00+00:00 1.049685e+05 2021-04-30 00:00:00+00:00 2.665753e+06

现在,在我们可以连接两个数据帧之前,请注意 yfinance 数据帧在索引中只有 日期,而余额数据具有完整的时间戳。我们可以将余额数据转换为索引中只有日期,如下所示:

dates = [d.date() for d in newdfb.index]
newdfb.index = pd.DatetimeIndex(dates)
newdfb.index.name = 'Time'
print(newdfb.head())
平衡 时间 2021-04-24 4.900000e+01 2021-04-26 2.009900e+04 2021-04-27 8.901000e+02 2021-04-29 1.049685e+05 2021-04-30 2.665753e+06

现在我们可以加入两个数据框。 DataFrame.join() 将根据索引加入数据帧,在我们的例子中是日期,因此数据将按日期对齐。此外,我们将进行 外部 连接和 .dropna(),以便只有两个数据帧中都存在的日期才会包含在最终数据帧中 .这是能够将数据一起绘制在同一个图上的最简洁的方法:

dfc = df.join(newdfb, how='outer').dropna()
dfc.index.name = 'Date'
print(dfc.head())
print(dfc.tail())
开盘 高 低 收盘 成交量 红利 股票分割 余额 日期 2021-04-24 0.249544 0.289390 0.229891 0.270212 11057578568 0 0 4.900000e+01 2021-04-26 0.251240 0.280452 0.248026 0.270674 5118886527 0 0 2.009900e+04 2021-04-27 0.271427 0.279629 0.264928 0.272188 3590611310 0 0 8.901000e+02 2021-04-29 0.323232 0.323881 0.296904 0.305169 5027354503 0 0 1.049685e+05 2021-04-30 0.304702 0.339757 0.302981 0.337561 5290390982 0 0 2.665753e+06 开盘 高 低 收盘 成交量 红利 股票分割 余额 日期 2021-09-19 0.241281 0.241285 0.231337 0.233142 892763953 0 0 1.246787e+06 2021-11-27 0.201429 0.209613 0.200871 0.205347 917785649 0 0 1.246788e+06 2021-12-10 0.169466 0.174610 0.164065 0.164422 845450410 0 0 3.396755e+06 2022-01-15 0.183644 0.193600 0.182676 0.185103 1878282290 0 0 2.720510e+06 2022-01-23 0.132960 0.143072 0.132819 0.141863 1006234946 0 0 2.740510e+06

现在,我们终于可以将“余额”与 ohlc 烛台一起绘制:

ap = mpf.make_addplot(dfc['Balance'])
mpf.plot(dfc,type='candle',addplot=ap)

这是结果图:

【讨论】:

    猜你喜欢
    • 2018-02-24
    • 2019-05-31
    • 2018-01-18
    • 2017-11-14
    • 2020-05-12
    • 2018-12-03
    • 2017-07-11
    • 1970-01-01
    • 2023-02-01
    相关资源
    最近更新 更多