如何在 Matplotlib 中使用 Pandas 正确绘制这两个数据集?

How can I properly graph these two datasets using Pandas in Matplotlib?

我有两个数据集,我试图相互绘制。

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

第二个数据集是狗狗币钱包 t运行sactions 的 CSV 文件,其中有一列名为“余额”,显示了狗狗币钱包在 t[=30= 时的余额]行动。余额随着加密货币的出现而波动 in/out。以下是供参考的 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()

在排列两个数据集的时间戳之前,csv 文件存在许多问题,必须先清理。

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

df = pd.read_csv('DSb5CvAXhXnzFoxmiMaWpgxjDF6CfMK7h2.csv', index_col=0, parse_dates=parse_dates)
                                                     Time                                   Amount                  Balance Balance, USD @ Price    Profit
Block
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    0,950 @ [=21=].135  4,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     5,646 @ [=21=].19  1,413
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    2,555 @ [=21=].169  0,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    6,282 @ [=21=].173  5,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    3,629 @ [=21=].167  6,594

有关此文件的几点注意事项:

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

我建议,开始时,只阅读时间和平衡列,并将时间列设置为索引。同时可以对数据进行倒序,使时间顺序从早到晚:

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))
                               Balance
Time                                  
2021-04-24 10:20:22+00:00      47 DOGE
2021-04-24 10:34:39+00:00      57 DOGE
2021-04-24 10:40:49+00:00      67 DOGE
2021-04-24 10:42:22+00:00      58 DOGE
2021-04-24 10:50:46+00:00      49 DOGE
2021-04-26 09:48:52+00:00  19,049 DOGE
2021-04-26 13:39:54+00:00      49 DOGE
2021-04-26 16:22:06+00:00  20,099 DOGE

现在您可以通过将列字符串拆分为实际余额和单词“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())
                                Balance
Time                                   
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
                                Balance
Time                                   
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())
                Open      High       Low     Close      Volume  Dividends  Stock Splits
Date
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
                Open      High       Low     Close      Volume  Dividends  Stock Splits
Date
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()(开盘价、最高价、最低价、收盘价)聚合器来完成,然后只需将每一天的“收盘价”作为该日期的最终余额:

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())
                            Balance
Time                                   
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())
                 Balance
Time                    
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() 将根据索引加入数据帧,在我们的例子中是日期,因此数据将按日期对齐。此外,我们将进行 outer 连接,并且 .dropna() 以便 只有存在于两个数据框中的日期才会包含在最终数据框中。这是能够将数据一起绘制在同一图上的最干净的方法:

dfc = df.join(newdfb, how='outer').dropna()
dfc.index.name = 'Date'
print(dfc.head())
print(dfc.tail())

                Open      High       Low     Close       Volume  Dividends  Stock Splits       Balance
Date
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
                Open      High       Low     Close      Volume  Dividends  Stock Splits       Balance
Date
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

现在终于可以绘制 'Balance' 和 ohlc 烛台了:

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

这是结果图: