Plotille
在终端中使用盲文点、前景色和背景色绘制图表、散点图、直方图和热图 - 无需任何依赖。使用Figure类创建复杂图形,或使用绘图函数快速简单地绘制图表 - 类似于matplotlib的小型版本。也可以使用画布自行绘制点、线和图像。
安装:
pip install plotille
与其他类似库的比较:
- 类似于drawille,但专注于绘图 - 并带有X/Y轴。
- 类似于termplot,但使用盲文(更精细的点)、从左到右的直方图和用于绘制函数的线性插值。
- 类似于termgraph(不在pypi上),但风格非常不同。
- 类似于terminalplot,但带有盲文、X/Y轴、直方图、线性插值。
3.2版本提供了对时间序列绘图的基本支持:对于任何X
或Y
值,你也可以添加datetime.datetime
、pendulum.datetime
或numpy.datetime64
值。标签会根据x_limits
和y_limits
的差异生成。
4.0版本提供了使用背景色绘制热图的功能,以及使用盲文二进制显示图像或使用画布的背景色显示彩色图像的功能。
如果你仍在使用Python 2.7,请使用plotille v4或更早版本。从v5开始,我将停止对Python 2.7的支持,因为维护这个已停止的版本的工作量太大。
文档
In [1]: import plotille
In [2]: import numpy as np
In [3]: X = np.sort(np.random.normal(size=1000))
Figure
构建图表的推荐方式是使用Figure
:
In [12]: plotille.Figure?
初始化签名:plotille.Figure()
文档字符串:
Figure类用于组合多个图表。
在Figure中,你可以轻松组合多个图表,为图表分配标签,
并定义底层Canvas的属性。可以定义的可能属性包括:
width, height: int 定义用于绘图的X / Y方向的字符数。
x_limits: float 定义将被绘制的参考坐标系的X限制。
y_limits: float 定义将被绘制的参考坐标系的Y限制。
color_mode: str 定义使用的颜色模式。参见`plotille.color()`。
with_colors: bool 定义是否使用颜色。
background: multiple 定义背景颜色。
x_label, y_label: str 定义X / Y轴标签。
基本上,你创建一个Figure
,定义属性并添加你的图表。使用show()
函数,Figure
会使用新的画布生成图表:
In [13] fig = plotille.Figure()
In [14] fig.width = 60
In [15] fig.height = 30
In [16] fig.set_x_limits(min_=-3, max_=3)
In [17] fig.set_y_limits(min_=-1, max_=1)
In [18] fig.color_mode = 'byte'
In [19] fig.plot([-0.5, 1], [-1, 1], lc=25, label='第一条线')
In [20] fig.scatter(X, np.sin(X), lc=100, label='正弦')
In [21] fig.plot(X, (X+2)**2 , lc=200, label='平方')
In [22] print(fig.show(legend=True))
可用的绘图函数有:
# 创建一个点之间使用线性插值的图
Figure.plot(self, X, Y, lc=None, interp='linear', label=None, marker=None)
# 创建一个点之间没有插值的散点图
Figure.scatter(self, X, Y, lc=None, label=None, marker=None)
# 创建X的直方图
Figure.histogram(self, X, bins=160, lc=None)
# 在坐标X, Y处打印文本
Figure.text(self, X, Y, texts, lc=None)
# 以下函数使用画布上的相对坐标
# 即所有坐标 \in [0, 1]
# 在x处绘制垂直线
Figure.axvline(self, x, ymin=0, ymax=1, lc=None)
# 从(xmin,ymin)到(xmax, ymax)绘制垂直矩形
Figure.axvspan(self, xmin, xmax, ymin=0, ymax=1, lc=None)
# 在y处绘制水平线
Figure.axhline(self, y, xmin=0, xmax=1, lc=None)
# 从(xmin,ymin)到(xmax, ymax)绘制水平矩形
Figure.axhspan(self, ymin, ymax, xmin=0, xmax=1, lc=None)
# 将数据显示为图像,即在2D规则栅格上
Figure.imgshow(self, X, cmap=None)
其他有趣的函数包括:
# 从图形中移除所有绘图、文本、跨度和图像
Figure.clear(self)
# 创建画布,绘制已注册的图表,并返回用于显示图表的字符串
Figure.show(self, legend=False)
请查看 examples/
文件夹。
图形绘制
这里有一些用于快速绘制单个图表的实用函数。
折线图
In [4]: plotille.plot?
签名:
plotille.plot(
X,
Y,
width=80,
height=40,
X_label='X',
Y_label='Y',
linesep=os.linesep,
interp='linear',
x_min=None,
x_max=None,
y_min=None,
y_max=None,
lc=None,
bg=None,
color_mode='names',
origin=True,
marker=None,
)
文档字符串:
使用 X、Y 值创建折线图,并在点之间进行线性插值
参数:
X: List[float] X 值列表。
Y: List[float] Y 值列表。X 和 Y 必须具有相同数量的元素。
width: int 画布宽度(列数)的字符数。
height: int 画布高度(行数)的字符数。
X_label: str X 轴标签。
Y_label: str Y 轴标签。最多 8 个字符。
linesep: str 请求的行分隔符。默认:os.linesep
interp: Optional[str] 指定插值方式;值可为 None 或 'linear'
x_min, x_max: float 显示的 X 值范围限制。
y_min, y_max: float 显示的 Y 值范围限制。
lc: multiple 设置线条颜色。
bg: multiple 设置背景颜色。
color_mode: str 指定颜色输入模式;'names'(默认)、'byte' 或 'rgb'
参见 plotille.color.__docs__
origin: bool 是否打印原点。默认:True
marker: str 用于替代盲文点的实际值标记字符。
返回:
str: 绘制 `X`、`Y` 的折线图。
In [5]: print(plotille.plot(X, np.sin(X), height=30, width=60))
散点图
In [6]: plotille.scatter?
签名:
plotille.scatter(
X,
Y,
width=80,
height=40,
X_label='X',
Y_label='Y',
linesep='\n',
x_min=None,
x_max=None,
y_min=None,
y_max=None,
lc=None,
bg=None,
color_mode='names',
origin=True,
marker=None,
)
文档字符串:
使用 X、Y 值创建散点图
基本上是不进行插值的绘图:
`plot(X, Y, ... , interp=None)`
参数:
X: List[float] X 值列表。
Y: List[float] Y 值列表。X 和 Y 必须具有相同数量的元素。
width: int 画布宽度(列数)的字符数。
height: int 画布高度(行数)的字符数。
X_label: str X 轴标签。
Y_label: str Y 轴标签。最多 8 个字符。
linesep: str 请求的行分隔符。默认:os.linesep
x_min, x_max: float 显示的 X 值范围限制。
y_min, y_max: float 显示的 Y 值范围限制。
lc: multiple 设置线条颜色。
bg: multiple 设置背景颜色。
color_mode: str 指定颜色输入模式;'names'(默认)、'byte' 或 'rgb'
参见 plotille.color.__docs__
origin: bool 是否打印原点。默认:True
marker: str 用于替代盲文点的标记字符。
返回:
str: 绘制 `X`、`Y` 的散点图。
In [7]: print(plotille.scatter(X, np.sin(X), height=30, width=60))
直方图
灵感来自 crappyhist(链接已失效,但我制作了一个 gist)。
In [8]: plotille.hist?
签名:
plotille.hist(
X,
bins=40,
width=80,
log_scale=False,
linesep='\n',
lc=None,
bg=None,
color_mode='names',
)
文档字符串:
从左到右创建 `X` 的直方图
左侧的值是桶的中心,即 `(bin[i] + bin[i+1]) / 2`。
右侧的值是该桶的总计数。
参数:
X: List[float] 要计数的项目列表。
bins: int 将 X 条目放入的桶数(行数)。
width: int 宽度(列数)的字符数。
log_scale: bool 使用 `log` 函数缩放直方图。
linesep: str 请求的行分隔符。默认:os.linesep
lc: multiple 设置线条颜色。
bg: multiple 设置背景颜色。
color_mode: str 指定颜色输入模式;'names'(默认)、'byte' 或 'rgb'
参见 plotille.color.__docs__
返回:
str: 从左到右绘制 `X` 的直方图。
In [9]: print(plotille.hist(np.random.normal(size=10000)))
聚合直方图
此函数允许您在数据已经聚合的情况下创建直方图(即您无法访问原始值,但可以访问每个桶的计数和桶边界)。
这在使用诸如 OpenTelemetry Metrics API 之类的 API 时非常有用,其中像 ExplicitBucketHistogramAggregation 这样的视图只提供对聚合值(每个桶/存储桶的计数)的访问。
In [8]: plotille.hist_aggregated?
签名:
plotille.hist_aggregated(
counts,
bins,
width=80,
log_scale=False,
linesep='\n',
lc=None,
bg=None,
color_mode='names',
)
文档字符串:
为聚合数据创建直方图。
参数:
counts: List[int] 每个桶的计数。
bins: List[float] 所提供计数的分桶限制:第 i 个分桶的限制为 [bins[i], bins[i+1])。
因此,len(bins) == len(counts) + 1。
width: int 宽度(列)的字符数。
log_scale: bool 使用 log 函数缩放直方图。
linesep: str 请求的行分隔符。默认值:os.linesep
lc: multiple 设置线条颜色。
bg: multiple 设置背景颜色。
color_mode: str 指定颜色输入模式;'names'(默认)、'byte'或'rgb'
参见 plotille.color.__docs__
返回:
str: 从左到右的 X 的直方图。
In [9]: counts = [1945, 0, 0, 0, 0, 0, 10555, 798, 0, 28351, 0]
In [10]: bins = [float('-inf'), 10, 50, 100, 200, 300, 500, 800, 1000, 2000, 10000, float('+inf')]
In [11]: print(plotille.hist_aggregated(counts, bins))
请记住,bins 的数量必须总是比 count 值的总数多 1 个(在上面的例子中是 11)。
在这个例子中,第一个 bin 是 [-inf, 10),计数为 1945,最后一个 bin 是 [10000, +inf],计数为 0。
直方图
还有另一个更"常规"的直方图函数可用:
In [10]: plotille.histogram?
签名:
plotille.histogram(
X,
bins=160,
width=80,
height=40,
X_label='X',
Y_label='Counts',
linesep='\n',
x_min=None,
x_max=None,
y_min=None,
y_max=None,
lc=None,
bg=None,
color_mode='names',
)
文档字符串:
创建 X 的直方图
与 hist 相比,这是更"常规"的从底部到顶部的直方图。X 轴表示 X 中的值,Y 轴是相应的频率。
参数:
X: List[float] 要计数的项目。
bins: int 将 X 条目放入的 bin 数量(列)。
height: int 高度的字符数(行)。
X_label: str X 轴标签。
Y_label: str Y 轴标签。最多 8 个字符。
linesep: str 请求的行分隔符。默认值:os.linesep
x_min, x_max: float 显示的 X 值的限制。
y_min, y_max: float 显示的 Y 值的限制。
lc: multiple 设置线条颜色。
bg: multiple 设置背景颜色。
color_mode: str 指定颜色输入模式;'names'(默认)、'byte'或'rgb'
参见 plotille.color.__docs__
返回:
str: X 的直方图。
In [11]: print(plotille.histogram(np.random.normal(size=10000)))
画布
底层绘图区域被建模为 Canvas 类:
In [12]: plotille.Canvas?
初始化签名:
plotille.Canvas(
width,
height,
xmin=0,
ymin=0,
xmax=1,
ymax=1,
background=None,
**color_kwargs,
)
文档字符串:
用于绘制盲文点的画布对象
Canvas 对象有一个 width x height 字符大小的画布,可以在其中绘制单个盲文点、由盲文点组成的线条、矩形等。
由于一个完整的盲文字符有 2 x 4 个点(⣿),画布总共有 width * 2, height * 4 个可绘制的点。
它维护两个坐标系:一个参考系统,左下角为(xmin, ymin),右上角为(xmax, ymax),
这个系统被转换为画布的离散坐标系统,即从(0, 0)到(width * 2, height * 4)的点。
对 Canvas 的客户端来说,这个转换是透明的,即所有绘图函数只接受参考系统中的坐标。
如果坐标在参考系统之外,则不会被绘制。
初始化文档字符串:
初始化 Canvas 对象
参数:
width: int 画布宽度(列)的字符数。
height: int 画布高度(行)的字符数。
xmin, ymin: float 参考系统的左下角。
xmax, ymax: float 参考系统的右上角。
background: multiple 画布的背景颜色。
**color_kwargs: 颜色函数的更多参数。参见 plotille.color()。
返回:
Canvas 对象
最有趣的函数有:
point:
In [11]: plotille.Canvas.point?
签名: plotille.Canvas.point(self, x, y, set_=True, color=None, marker=None)
文档字符串:
在画布的(x, y)位置[参考坐标系]放置一个点
参数:
x: float 参考系统上的 x 坐标。
y: float 参考系统上的 y 坐标。
set_: bool 是绘制还是移除该点。
color: multiple 点的颜色。
marker: str 用标记字符替代盲文点。
line:
In [14]: plotille.Canvas.line?
签名: plotille.Canvas.line(self, x0, y0, x1, y1, set_=True, color=None)
文档字符串:
在点(x0, y0)和(x1, y1)之间绘制线条[参考坐标系]。
参数:
x0, y0: float 点 0
x1, y1: float 点 1
set_: bool 是绘制还是移除该线条。
color: multiple 线条的颜色。
rect:
In [15]: plotille.Canvas.rect?
签名: plotille.Canvas.rect(self, xmin, ymin, xmax, ymax, set_=True, color=None)
文档字符串:
用边界框(xmin, ymin)和(xmax, ymax)绘制矩形[参考坐标系]。
参数:
xmin, ymin: float 矩形的左下角。
xmax, ymax: float 矩形的右上角。
set_: bool 是绘制还是移除该矩形。
color: multiple 矩形的颜色。
text:
In [16]: plotille.Canvas.text?
签名: plotille.Canvas.text(self, x, y, text, set_=True, color=None)
文档字符串:
在画布的(x, y)位置[参考坐标系]放置一些文本
参数:
x: float 参考系统上的 x 坐标。
y: float 参考系统上的 y 坐标。
set_: bool 是设置文本还是清除字符。
text: str 要添加的文本。
color: multiple 点的颜色。
braille_image:
```python
In [17]: plotille.Canvas.braille_image?
签名:
plotille.Canvas.braille_image(
self,
pixels,
threshold=127,
inverse=False,
set_=True,
)
文档字符串:
使用盲文点将图像打印到画布上。
画布中的像素和盲文点是一对一映射的,因此
一个80 x 80像素的图像需要一个40 x 20的画布。
示例:
from PIL import Image
import plotille as plt
img = Image.open("/path/to/image")
img = img.convert('L')
img = img.resize((80, 80))
cvs = plt.Canvas(40, 20)
cvs.braille_image(img.getdata(), 125)
print(cvs.plot())
参数:
pixels: list[number] 图像的所有像素组成的列表。
threshold: float 高于此阈值的所有像素将被
绘制。
inverse: bool 是否反转图像。
set_: bool 是否绘制或移除点。
image:
In [18]: plotille.Canvas.image?
签名: plotille.Canvas.image(self, pixels, set_=True)
文档字符串:
使用背景颜色将图像打印到画布上。
图像的像素和画布中的字符是一对一映射的,
因此一个80 x 80的图像需要一个80 x 80的画布。
示例:
from PIL import Image
import plotille as plt
img = Image.open("/path/to/image")
img = img.convert('RGB')
img = img.resize((40, 40))
cvs = plt.Canvas(40, 40, mode='rgb')
cvs.image(img.getdata())
print(cvs.plot())
参数:
pixels: list[(R,G,B)] 图像的所有像素组成的列表。
set_: bool 是否绘制或移除背景
颜色。
plot:
In [16]: plotille.Canvas.plot?
签名: plotille.Canvas.plot(self, linesep='\n')
文档字符串:
将画布转换为可`print`的字符串
参数:
linesep: str 请求的行分隔符。默认值: os.linesep
返回:
unicode: 作为字符串的画布。
例如,你可以用它在终端中绘制一个房子:
In [17]: c = Canvas(width=40, height=20)
In [18]: c.rect(0.1, 0.1, 0.6, 0.6)
In [19]: c.line(0.1, 0.1, 0.6, 0.6)
In [20]: c.line(0.1, 0.6, 0.6, 0.1)
In [21]: c.line(0.1, 0.6, 0.35, 0.8)
In [22]: c.line(0.35, 0.8, 0.6, 0.6)
In [23]: print(c.plot())
或者你可以用盲文点渲染图像:
In [24]: img = Image.open('https://github.com/tammoippen/plotille/raw/master/imgs/ich.jpg')
In [25]: img = img.convert('L')
In [26]: img = img.resize((80, 80))
In [27]: cvs = Canvas(40, 20)
In [28]: cvs.braille_image(img.getdata())
In [29]: print(cvs.plot())
或者你可以用字符的背景色渲染图像:
In [24]: img = Image.open('https://github.com/tammoippen/plotille/raw/master/imgs/ich.jpg')
In [25]: img = img.convert('RGB')
In [25]: img = img.resize((80, 40))
In [27]: cvs = Canvas(80, 40, mode="rgb")
In [28]: cvs.image(img.getdata())
In [29]: print(cvs.plot())