当前位置:首页>python>我们是否还需要一个python的ggplot2?

我们是否还需要一个python的ggplot2?

  • 2026-06-27 19:49:19
我们是否还需要一个python的ggplot2?

R 用户从 R 切回 Python 想画同样的图,默认选项是 plotnine。它把 Grammar of Graphics 在 Python 里实现得相当成熟,API 几乎和 R 端 ggplot2 逐字对应。但渲染那一头,plotnine 落在 matplotlib 上 —— 这是 Python 可视化生态的事实标准。问题不在 plotnine 写得好不好,而在 matplotlib 的 Figure / Axes / Artist 模型里,没有 R 端 grid 包提供的那一层 abstract layout —— 没有可延迟解析的 Unit 表达式系统,没有 viewport 嵌套栈,没有 gtable 这种由网格化 grob 拼出整图的整体编排抽象。GoG 概念里像 panel、strip、legend 槽位、axis 边距、theme(plot.background=...) 这些,在 R + grid 模型里是一阶对象,在 matplotlib 模型里需要靠 Axes / Figure 的属性堆叠加 tight_layout / subplots_adjust 这类启发式后处理。

Bio-Babel/ggplot2-python 这个新项目选了另一条路:不在 matplotlib 之上再贴一层,而是把 R 的整条底层栈(grid / gtable / scales)一起移植到 Python,然后让 ggplot 跑在 Python 端的 grid 上。代价是工作量翻了好几倍 —— 三个上游包都得自己端口;收益是 GoG 在 Python 里第一次有了和 R 端同构的分层抽象。

总览

本文沿着仓库 tutorials/geoms_gallery.ipynb 全部 cells 走一遍,先讲为什么 Python 还需要这个项目,再展示它在 5 个核心 geom(boxplot / violin / density / tile / hex)以及多层叠加上的 API 与 R 端 ggplot2 几乎一致。 重点是架构层面:+ 操作符、layer stack、scale 系统、coord 转换,最终如何落到 grid 上的 gtable 编排,共同构成了 GoG 在 Python 里第一次完整的 abstract layout 实现。

Grammar of Graphics 在 R 里为什么成立

Grammar of Graphics 这个概念出自 Leland Wilkinson 1999 年的 The Grammar of Graphics(Springer)。Hadley Wickham 2005 年开始在 R 里把它实现成 ggplot2,2016 年的 ggplot2: Elegant Graphics for Data Analysis(Springer 2nd ed)是经典参考。GoG 的核心想法是:任何统计图形都能拆成几个正交组件 —— data、aesthetic mapping、geom、stat、coord、facet、scale、theme,它们能用 + 任意组合。

R 端 ggplot2 之所以能把 GoG 落实成一个干净可扩展的库,关键是它没有自己造图形底层,而是建在 R 的三个底层包之上:

  • grid
    (R core 自带):一个抽象的二维布局系统。它提供 Unit(单位表达式:npccmlinesstrwidth 等可以混合算术,Unit(1, "npc") - Unit(2, "lines") 这种表达式在 viewport push 时延迟解析)、Viewport(可嵌套的视口,带局部坐标系)、Grob(图形对象树)。layout 不是函数式后处理,是一阶对象。
  • gtable
    (Wickham 维护):基于 grid 的网格表格布局,把 grob 装进 row × col 的 cell。一个 ggplot 的最终产物本质上是一张 gtable —— title / subtitle 行、strip / panel / axis 行、legend 列、margin —— 全是 gtable cell。
  • scales
    (Wickham 维护):统一抽象数据空间 ↔ 美学空间(色板、形状、大小)的训练 / 映射 / 反向映射,提供 breaks / labels / log10 / sqrt / reverse 等 transforms。

ggplot2 在 R 里的代码量本身不算庞大,真正繁重的工作分担到了这三个上游包。GoG 的语法之所以"干净",是因为有这套底层抽象兜底。

Python 这边过去缺的是什么

Python 之前缺的一直就是这套上游栈。matplotlib 不是它们的对应物 —— matplotlib 是一个完整的渲染引擎,但它的层级模型(Figure → Axes → Artist)里没有"延迟解析的 Unit 表达式"这种抽象,也没有 gtable 那种"整图 = 一张 cell 网格"的整体编排原语。

在这种基础上写一个 GoG 实现 —— plotnine(has2k1/plotnine)就是这条路 —— 完全可以让 API 对得上 R 端,且实测做得很好;但 GoG 里的某些抽象只能就近映射到 matplotlib 的相邻概念 + 一些启发式后处理。这不是 plotnine 的问题,是底层选择的问题:matplotlib 的设计目标是"通用绘图引擎",不是"R 的 grid"。

ggplot2-python 选择的工作量是把上游栈也搬过来。

ggplot2-python 怎么解这个问题

仓库 pyproject.toml 的依赖列表直接给出了答案:

# pyproject.toml(节选)dependencies = [    "rgrid-python>=4.5.3",    "gtable-python>=0.3.6",    "scales-python>=1.4.0",    "numpy>=1.24",    "pandas>=1.5",    "scipy>=1.10",    ...]

rgrid-python(import 名 grid_py)是 R grid 包的 Python 端口,提供 UnitViewportGridLayoutgrid_drawgrid_newpage 等核心原语,以及一个 Cairo 后端的 CairoRenderer(默认)和一个 WebRenderer(产生 SVG + Canvas + D3 的可交互 HTML)。gtable-python 是 R gtable 包的端口。scales-python 是 R scales 包的端口,统一处理 colour 映射、breaks / labels、log10 / sqrt / reverse 等 transforms。

ggplot2-python 自己的实现里不直接 import matplotlib:在仓库根 grep -ln "import matplotlib" ggplot2_py/*.py 返回为空(labeller.py 与 save.py 仅在文档字符串里提到 matplotlib mathtext / savefig 的命名习惯,不依赖)。整条渲染走的是 grid_py:

# ggplot2_py/plot.py: GGPlot._repr_png_from grid_py import grid_draw, grid_newpagegrid_newpage(width=fig_width, height=fig_height, dpi=fig_dpi)built  = ggplot_build(self)        # 16-stage 数据管线gtable = ggplot_gtable(built)      # 编排成一张 gtablegrid_draw(gtable)                  # 在 viewport 栈里逐 grob 解析 Unit

ggplot_build 中的 16 个 stage 在BuildStage(plot.py:593-624)里命名:LAYER_DATASETUP_LAYERSETUP_LAYOUTCOMPUTE_AESTHETICSTRANSFORM_SCALESTRAIN_POSITIONCOMPUTE_STATMAP_STATCOMPUTE_GEOM_1COMPUTE_POSITIONRETRAIN_POSITIONSETUP_GUIDESTRAIN_NONPOSITIONCOMPUTE_GEOM_2FINISH_STATFINISH_DATA。每一个 stage 前 / 后都能挂 hook —— R 端没有这种扩展面。

ggplot_gtable(plot_render.py:215-300)把每层 layer 调 draw_geom(...) 得到的 grob 列表交给 Layout.render(...) 排进 panel 槽,再依次把 legend(R 3.5+ 的 right / left / top / bottom / inside 五个槽位)、title / subtitle / caption / tag、plot.margin padding、plot.background 元素(以 z=-Inf 垫底)全部以 grob 的形式装进 gtable。这就是这个项目的核心:你写的 ggplot(...) + geom_xxx() + ... 表达式,在最终渲染前是一棵真正的 grid grob 树。

上手:geoms_gallery 全程

仓库自带 9 个 tutorial notebook,这一篇追 tutorials/geoms_gallery.ipynb 走完。它依次演示 5 个核心 geom 的多个变体加最后的层叠组合。先把环境装起来:

from ggplot2_py import *from ggplot2_py.plot import GGPlotfrom ggplot2_py.datasets import mpg, diamondsimport pandas as pdimport numpy as np

mpg 是 234 行 × 11 列的车型数据(R 用户熟悉),diamonds 是 53940 行的钻石定价数据 —— 都是 ggplot2 经典示例集,通过 datasets.py 直接打包提供。

GGPlot.fig_width = 5GGPlot.fig_height = 4GGPlot.fig_dpi = 100

注意这里改的是类属性,所以是全局默认 —— 后续每个 plot 出图都按这个尺寸来。R 端没有这种写法(R 里你改 device,不改 plot),但 Python 把它做成 GGPlot.fig_width 这样的类属性更顺手,Jupyter 显示时(_repr_png_)直接走这套默认值。

geom_boxplot

geom_boxplot 在 GoG 里属于一个 statistical layer:它绑定 stat_boxplot,从原始数据按 group 算 5-number summary(min / Q1 / median / Q3 / max)和 1.5 × IQR outlier 阈值,再把这些聚合值落成 box 形 grob。所以你不需要自己 pre-compute 这些值 —— aes() 给 raw 数据,stat 自动跑。

# Basic boxplotggplot(mpg, aes(x='class', y='hwy')) + geom_boxplot()

x='class' 是离散变量(7 个车型类别),y='hwy' 是连续变量(高速油耗 mpg)。x 离散,所以 stat_boxplot 按 class 分组算 summary,落到一个 panel 上 7 个 box。

加一个 fill 美学:

# Filled boxplot with colour by drive trainggplot(mpg, aes(x='class', y='hwy', fill='drv')) + geom_boxplot()

fill='drv' 让 stat 在 class × drv 二维网格上算 group。注意没有写任何 position_dodge(...),但每个 class 内不同 drv 的 box 自动并排开 —— 这是因为 geom_boxplot 的 default position 已经是 position_dodge2。GoG 的 position 是独立组件,你也可以显式覆盖。

横躺一下:

# Horizontal boxplot with coord_flipggplot(mpg, aes(x='class', y='hwy')) + geom_boxplot() + coord_flip()

coord_flip() 是 coord 子系统的一个 transform。GoG 设计里 coord 与 geom 正交,所以 boxplot、violin、histogram、scatter 都能加 coord_flip() 互换 x/y。在 ggplot2-python 实现层面这一步落在 coord.py(全文 114 KB,5 种 coord),它在 SETUP_LAYOUT 阶段挂进 Layout,后续 transform() 把 panel-local 坐标换轴。

geom_violin

violin 是 boxplot 的 KDE 版:同样是离散 x × 连续 y,stat_ydensity 在每个 group 内做一维 KDE,把密度估计落成对称的 violin 形 grob。

# Basic violinggplot(mpg, aes(x='class', y='hwy')) + geom_violin()

形状由数据本身的分布决定。注意每个 class 的 violin 横宽默认按"相对峰值"归一化,不直接表达样本量;如果想让宽度跟样本量挂钩,可以加 geom_violin(scale="count")

# Filled violinggplot(mpg, aes(x='class', y='hwy', fill='class')) + geom_violin(alpha=0.6)

fill='class' 把分类变量映射到颜色;alpha=0.6 是 fixed aesthetic(geom 参数级,不参与 mapping)。GoG 区分 mapped aesthetic(写在 aes() 里,经过 scale 训练 / 映射)和 fixed aesthetic(写在 geom 参数里,所有 grob 共享同一值)—— 两者最终都落到 grob 的 Gpar(...) 字段。

geom_density

# Single density curveggplot(mpg, aes(x='hwy')) + geom_density()

只指定 x 时,stat_density 做一维 KDE(默认 Gaussian kernel,bandwidth 走 nrd0)。y 由 stat 自动算出 —— 这是默认的 after_stat(density)

# Overlapping densities by groupggplot(mpg, aes(x='hwy', fill='drv')) + geom_density(alpha=0.5)

加 fill='drv' 后,stat_density 按 drv 分三组分别 KDE,落三条带填色的密度曲线;alpha=0.5 让重叠区域可见。

# Density with colour outline onlyggplot(mpg, aes(x='hwy', colour='drv')) + geom_density(linewidth=1)

把 fill 改成 colour(GoG aesthetics 里两个独立通道:面填 vs 边描),曲线只描边、不填面。linewidth=1 是 fixed aesthetic 控制线宽。这就是 GoG 美学正交性的好处:同一份数据,切换"填面 / 描边"只是改一个映射目标,不需要换 geom。

geom_tile

tile 是把每个 (x, y) 对应一个矩形 cell,用 fill 通道编码 z 值 —— 也就是标准热力图。

# Simple 5x5 heatmapnp.random.seed(42)tile_data = pd.DataFrame({    'x': np.repeat(range(5), 5),    'y': np.tile(range(5), 5),    'z': np.random.randn(25),})ggplot(tile_data, aes('x', 'y', fill='z')) + geom_tile()

默认 fill 走 scale_fill_gradient —— 蓝白(低值偏蓝,高值偏白)。这是 scales-python 提供的连续 fill scale。

# Tile with viridis colour scaleggplot(tile_data, aes('x', 'y', fill='z')) + geom_tile() + scale_fill_viridis_c()

加一个 scale_fill_viridis_c(),整张图的 fill scale 就被替换成 viridis 调色板(perceptually uniform 色系)。Scale 是独立 GoG 组件:你不修改 geom,不修改数据,只在最后 + 一个新的 scale,渲染时数据 → 颜色的映射就被替换。这是 GoG 真正"语法化"的地方,也是 scales-python 这个上游包的价值所在。

geom_hex

当散点图重叠太重看不清时,hex binning 是经典解法:把绘图区切成六边形 bin,用 fill 通道编码每个 bin 的点数。

# Hexagonal binningggplot(mpg, aes(x='cty', y='hwy')) + geom_hex()

stat_binhex 默认在 30 × 30 的 hex 网格上做 2D bin,默认 fill 是 count,自动接 continuous fill scale。

# Hex with fewer binsggplot(mpg, aes(x='cty', y='hwy')) + geom_hex(bins=15)

bins=15 调粗粒度。这个参数在 stat 级(传给 stat_binhex),不是 geom 级 —— ggplot2-python 自动按"stat 参数 / geom 参数 / aes 参数"分类路由进去,不需要写 stat_binhex(bins=15) + geom_hex()

Combining geoms

GoG 最有说服力的地方是 layer 加法。同一个 ggplot 上叠多个 layer,每层独立算 stat,最后一起进 panel:

# Boxplot + jittered points(    ggplot(mpg, aes(x='class', y='hwy'))    + geom_boxplot(alpha=0.3)    + geom_jitter(width=0.2, size=0.8, alpha=0.5))

box 给出分布概要,jitter 露出原始点数。两层共用同一份 aes() mapping,geom_boxplot 内部走 stat_boxplot,geom_jitter 内部用 position_jitter 给原始点加扰动避免重叠。注意是 geom_jitter 而不是 geom_point() + position_jitter() —— ggplot2 给常用组合做了 convenience geom,但二者本质等价。

# Density + rug marksggplot(mpg, aes(x='hwy')) + geom_density(fill='steelblue', alpha=0.4) + geom_rug()

底部那一排短竖线是 geom_rug —— 它把每个观测的 x 投影到底边的小 tick。配合 density 曲线,你既看见分布形状,也看见样本支持的具体位置。fill='steelblue' 是 fixed aesthetic 写在 geom 参数里。

# Scatter + hex overlay(    ggplot(mpg, aes(x='cty', y='hwy'))    + geom_hex(alpha=0.8)    + geom_point(size=0.8, alpha=0.4))

hex 提供密度,point 提供个体观测的位置感。两层都从同一份 aes() 拿 x / y,各自完成 stat,落成两个独立 grob 进入同一 panel 的 gtable cell。这种组合在大数据散点图里特别有用 —— 既保留点级别可解释性,又避免完全 overplot 看不清。

到这里 geoms_gallery.ipynb 25 个 cell 走完了。你应该能感到:每一个 plot 都是一个用 + 串起来的表达式,数据 + 美学 + geom + (optional)stat / scale / coord —— 写法和 R 端的 ggplot2 几乎逐字对应。

Python-exclusive 扩展点

把 ggplot2 整套搬到 Python 之后,作者还顺手加了一些 R 没有的 Python 习惯写法。这些不修改 GoG 本身,只是扩展机制:

  • Callable aes()
    :aes(y=lambda d: np.log(d["mpg"])) —— 直接在 mapping 里嵌一个 lambda,不需要先在 dataframe 里 pre-compute 一列。after_stat() / after_scale() 同样支持 callable,可以在 stat 算完 / scale 映射完之后再插一个表达式,例如 aes(y=after_stat(lambda d: d["count"] / d["count"].sum())) 把直方图 count 归一化为比例。
  • Build hooks 16 stages
    :p.add_build_hook("after", BuildStage.COMPUTE_STAT, fn) —— 在 16 个具名阶段里挑一个,前 / 后挂回调。给做 ggplot 二次开发(自定义 stat、调试 pipeline)的人准备的扩展面。
  • @update_ggplot.register(MyClass)
    :基于 functools.singledispatch,任何 Python 类都能注册成 + 操作符的合法右值。ggplot_build 自身也是 singledispatch,扩展包能整体替换 build pipeline。
  • @runtime_checkable Protocols
    :ggplot2_py/protocols.py 给 Geom / Stat / Scale / Coord / Facet / Position 各定义了一个 Protocol,可以 isinstance(my_geom, GeomProtocol) 在运行时检结构是否符合契约。R 那边没有这套机制。
  • Auto-registration via __init_subclass__
    :class GeomStar(Geom): ... 写完不需要再手动调注册函数,Python 元编程自动接进 ggplot 的 geom 注册表。
  • Scoped defaults
    :with ggplot_defaults(theme=theme_minimal()): ... —— 用 contextvars.ContextVar 实现的作用域默认,出 with 块就还原。比 R 端 theme_set() 全局污染的写法更安全。

这些是项目的"+1"。GoG 本身不需要它们,但它们让 ggplot2-python 在 Python 生态里更像 Python。

结尾

回到开头那个问题:Python 已经有 plotnine,我们是否还需要一个 ggplot2-python?

如果你只是要在 Python 里画 GoG 风格图,plotnine 一直够用,这两年它的成熟度也不低 —— 答案是"不一定"。但如果你的工作经常在 R 与 Python 之间穿梭,或者要做 ggplot 的二次开发(自定义 stat / theme、改 build pipeline、写扩展包),ggplot2-python 提供的"对齐 R 上游栈"是有意义的:

  • 一份 R ggplot 代码翻成 Python,几乎是逐行替换 <- 为 = 加 + ggplot() 链式调用
  • R 那边 grid / gtable / scales 的能力,在 Python 端能用同名概念调到
  • 16-stage build hooks 是 R 端没有的扩展面;callable aes / after_stat / after_scale 让 Python 习惯写法直接进 GoG

代价是对 grid / gtable / scales 的依赖更深,这是一个明显"重栈"的选择 —— 工作量大,但抽象边界清晰。Python 用户需不需要这条线,取决于你的工作流离 R 有多近。


代码: https://github.com/Bio-Babel/ggplot2-python;

本文示例来源的教程: https://github.com/Bio-Babel/ggplot2-python/tree/main/tutorials;

依赖: rgrid-python(R grid 端口) / gtable-python / scales-python;

如何联系我们

留一个领取资料开箱即用的单细胞分析镜像微信号[Biomamba_zhushou],方便各位随时交流。同时我们也构建了交流群矩阵欢迎大家入群讨论。
大家可以阅读完这几篇之后添加
给生信入门初学者的小贴士
没有检索,就没有发言权

已有生信基地联系方式的同学无需重复添加

您点的每个赞和在看,我都认真当成了喜欢

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-02 23:26:45 HTTP/2.0 GET : https://f.mffb.com.cn/a/500494.html
  2. 运行时间 : 0.244709s [ 吞吐率:4.09req/s ] 内存消耗:4,812.88kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=b1485a60ed4d27a503291b44317a0ae8
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.001089s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001875s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000837s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000759s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001332s ]
  6. SELECT * FROM `set` [ RunTime:0.000565s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001498s ]
  8. SELECT * FROM `article` WHERE `id` = 500494 LIMIT 1 [ RunTime:0.001155s ]
  9. UPDATE `article` SET `lasttime` = 1783006005 WHERE `id` = 500494 [ RunTime:0.046129s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.001100s ]
  11. SELECT * FROM `article` WHERE `id` < 500494 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.001565s ]
  12. SELECT * FROM `article` WHERE `id` > 500494 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.001366s ]
  13. SELECT * FROM `article` WHERE `id` < 500494 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.009659s ]
  14. SELECT * FROM `article` WHERE `id` < 500494 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.003146s ]
  15. SELECT * FROM `article` WHERE `id` < 500494 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.003512s ]
0.251033s