前言
虽然 Python 大行其道,但许多中大型企业核心系统还是以Java或C#为主,另外,Python要作出漂亮的UI介面也有困难,因此,笔者一直以来都想使用C#结合Python强大的生态环境(Ecosystem),作出漂亮的资料科学应用程式,日前刚好看到一篇好文『Getting Started With C# DataFrame and XPlot.Plotly』,介绍使用C#操作DataFrame,并绘製漂亮的统计图,虽然还没办法变成独立的执行档(Exe),但也算前进了一大步。
安装
步骤如下:
1.安装 Visual Studio:注意,不是Visual Studio Code,笔者目前仍使用 Visual Studio 2019,若读者使用Visual Studio 2022,须注意以下套件的版本。
2.安装在cmd下的互动式工具。
dotnet tool install --global Microsoft.dotnet-interactive --version 1.0.155302
将互动式工具整合至 Jupyter Notebook 环境中。dotnet interactive jupyter install
测试
大功告成,启动Notebook测试,新增一个C#档案,如下图:
在第一格输入:
Console.WriteLine("hello world !!");
顺利输出hello world !!
如果在网路抓一个C#的Notebook档案(.ipynb),在开启档案后,选择【Kernel】>【Change kernel】>【.net(C#)】即可。
DataFrame操作
安装套件:Visual Studio一般使用NuGet指令安装,Eikon Data API 支援在Jupyter中使用这项功能,同时,Microsoft.Data.Analysis套件支援DataFrame及统计图(XPlot.Plotly),故先安装这两个套件。#r "nuget:EikonDataAPI"#r "nuget:Microsoft.Data.Analysis,0.4.0"
注意版本,VS 2022应可使用最新版。
载入套件。using XPlot.Plotly;using Microsoft.Data.Analysis;using System.Linq;using Microsoft.AspNetCore.Html;
注册DataFrame的格式化函数(Formatter)。// 格式化 DataFrameFormatter.Register<DataFrame>((df, writer) =>{ var headers = new List<IHtmlContent>(); headers.Add(th(i("index"))); headers.AddRange(df.Columns.Select(c => (IHtmlContent) th(c.Name))); var rows = new List<List<IHtmlContent>>(); var take = 100; // 最多只显示100列,可调整 for (var i = 0; i < Math.Min(take, df.Rows.Count); i++) { var cells = new List<IHtmlContent>(); cells.Add(td(i)); foreach (var obj in df.Rows[i]) { cells.Add(td(obj)); } rows.Add(cells); } var t = table( thead( headers), tbody( rows.Select( r => tr(r)))); writer.Write(t); writer.Write(df.Rows.Count + " x "+df.Columns.Count);}, "text/html");// 格式化 DataFrame 的列Formatter.Register<DataFrameRow>((dataFrameRow, writer) =>{ var cells = new List<IHtmlContent>(); cells.Add(td(i)); foreach (var obj in dataFrameRow) { cells.Add(td(obj)); } var t = table( tbody( cells)); writer.Write(t);}, "text/html");
读取 CSV 档,并显示DataFrame,ohlcdata.csv来自这里。var df1 = DataFrame.LoadCsv("");df1
输出如下图:
作图
Microsoft.Data.Analysis 支援 Ploty 统计图,它是以Javascript开发的,有Tooltip,呈现内容比Matplotlib丰富。
线图。var chart1 = Chart.Plot( new Graph.Scatter { x = df1.Columns["Date"], y = df1.Columns["Close"], mode = "lines+markers" });var chart1_layout = new Layout.Layout{ title="Close Price", xaxis =new Graph.Xaxis{ title = "Date" }, yaxis =new Graph.Yaxis{ title = "Price (USD)" } };chart1.WithLayout(chart1_layout);chart1
输出如下图:
// 将 Date 栏位转成日期资料型态df1.Columns["Date"] = new PrimitiveDataFrameColumn<DateTime>("Date", df1.Columns["Date"] .Cast<object>() .ToList() .Select(x => DateTime.ParseExact(x.ToString(), "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture)) .Cast<DateTime>());
K 线图。var candle_chart = Chart.Candlestick(df1.OrderBy("Date").Rows.Select(row => new Tuple<string, double, double, double, double>( ((DateTime)row[0]).ToString("yyyy-MM-dd"), double.Parse(row[1].ToString()), double.Parse(row[2].ToString()), double.Parse(row[3].ToString()), double.Parse(row[4].ToString()) )));candle_chart.WithLayout(new Layout.Layout{ title="OHLC", xaxis =new Graph.Xaxis{ title = "Date" }, yaxis =new Graph.Yaxis{ title = "Price (USD)" } });candle_chart
输出如下图:
结论
对于 C# 与 Python 整合的议题,本来寄望微软.net基金会支援的IronPython,不过,它没办法支援 Python 套件,版本更新的速度也很缓慢,现在看到Microsoft.Data.Analysis,似乎出现一道曙光,希望未来可以有更多的套件支援。
相关程式在这里。