问题:LLM 和 Jupyter Notebook 天生有点别扭

那天凌晨两点,我终于承认自己卡住了。我的基因测序分析停在半路,因为 Cursor IDE 里的 LLM 助手始终没法稳定处理 Jupyter Notebook 那套复杂的 JSON 结构。每次让 AI 帮我改可视化代码,最后得到的都是损坏的 JSON,连笔记本都打不开。我也试过只贴几段代码片段,但这样又丢掉了前面数据预处理的上下文。与此同时,我桌面上还开着三个窗口:浏览器里的 Jupyter、用来认真写代码的 VSCode,以及另一个专门写文档的编辑器。Jupyter 的文件格式、LLM 的局限,再加上不停切换上下文,让复杂的数据分析很难顺畅推进。即便只是 Iris 这种更简单的示例数据集,这种根本性的错位也一直在吞掉我的效率。

如果你也做过数据分析,这种感觉应该不陌生。数据科学工作流最折磨人的地方之一,就是你总得在这些工具之间来回跳:

  • 写代码的编辑器
  • 做探索分析的 Jupyter Notebook
  • 用来整理结论的文档工具
  • 专门制作图表的可视化软件
  • 浏览器里开着的 ChatGPT 和 Claude

每切换一次,都会消耗一点注意力,也会让整个分析过程多一层阻力。但如果有一种方式,能把这些环节尽量合到一起呢?

更喜欢视频教程? 我录了一份完整的分步演示。观看在 Cursor IDE 中使用 Jupyter Notebook 与 AI 做数据分析的视频教程,可以直接看到整套流程是怎么跑起来的。

在 Cursor IDE 中完成数据可视化后的 Jupyter 工作流效果图

发现:把 Jupyter、IDE 和 LLM 放进同一套工作流

后来我找到了一种彻底改变工作方式的办法:直接在 Cursor IDE 里使用 Jupyter Notebook,再把 AI 能力叠加上去。这种做法把几个关键优势放到了同一个环境里:

  • Jupyter 按单元交互执行的体验
  • IDE 才有的编辑、搜索和导航能力
  • 能理解代码和数据分析任务的 AI 辅助
  • 更适合版本控制的纯文本文件格式

读完这篇文章,你会看到我是怎么搭出一个一体化环境,让自己能够:

  • 用更少的手写代码完成数据分析和可视化
  • 创建能帮助发现隐藏模式的 3D 可视化
  • 在代码旁边直接记录分析过程和结论
  • 用一条命令导出专业级报告
  • 尽量不在不同工具之间来回切换

如果你也受够了这种被工具打断的感觉,我们就从这里开始。

在 Cursor IDE 中搭建 Jupyter 环境:先把基础打好

顺手的工作流,前提都是环境先搭对。要在 Cursor IDE 里用好 Jupyter,先把工具装齐,再把 Python 环境整理清楚。

安装 Jupyter 扩展

整套流程的起点,是 Cursor IDE 的 Jupyter 扩展:

  1. 打开 Cursor IDE,创建一个项目目录
  2. 在侧边栏进入 Extensions
  3. 搜索 Jupyter,找到官方扩展
  4. 点击 Install

这个扩展相当于传统 Notebook 和 IDE 之间的桥梁。它带来的关键能力是:你可以在普通 Python 文件里,用特殊标记创建可执行单元。这样就不必再依赖结构复杂的 .ipynb 文件,而是可以直接用纯文本 Python 文件完成整套 Notebook 工作流。

如果你想进一步了解 Jupyter Notebook 的能力,可以查看 Jupyter Notebook 官方文档

准备 Python 环境

扩展装好以后,接着准备一个规范的 Python 环境:

python -m venv .venv

然后创建一个 pyproject.toml 文件来管理依赖:

[build-system]
requires = ["setuptools>=42.0", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "jupyter-cursor-project"
version = "0.1.0"
description = "Data analysis with Jupyter in Cursor IDE"
   
[tool.poetry.dependencies]
python = "^3.9"
jupyter = "^1.0.0"
pandas = "^2.1.0"
numpy = "^1.25.0"
matplotlib = "^3.8.0"
seaborn = "^0.13.0"
scikit-learn = "^1.2.0"

接着在虚拟环境里安装这些依赖:

pip install -e .

我是在踩过坑之后才意识到,版本冲突很容易引发一些看起来莫名其妙的错误。只要 AI 生成的代码要导入某个库,最好先确认它确实已经安装在当前环境里。

创建你的第一个 Notebook:纯文本方式的优势

传统 Jupyter Notebook 使用 .ipynb 格式,本质上是一套复杂的 JSON 结构。这个格式既不适合直接编辑,也几乎不可能让 AI 在不破坏结构的前提下稳定修改。相比之下,纯文本方式能把两边的优点结合起来。

原生 Jupyter Notebook 的问题

下面是一个传统 .ipynb 文件在文本编辑器里打开时的样子:

{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# My Notebook Title\n",
        "This is a markdown cell with text."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "metadata": {},
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": ["Hello, world!"]
        }
      ],
      "source": [
        "print(\"Hello, world!\")"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}

这种结构对 Cursor 所用的 LLM 来说尤其麻烦,主要有几个原因:

传统 Jupyter 笔记本文件的复杂 JSON 结构

  1. JSON 里有大量和实际内容无关的符号与嵌套结构
  2. 每个单元的内容都被存成字符串数组,还带着换行和引号转义
  3. 代码和输出分散在结构的不同位置
  4. 哪怕只改一小处,也得理解整个 JSON schema 才不至于把文件弄坏
  5. 内容稍微变动一下,JSON diff 就会变得很大,AI 很难精确地产生修改

当 LLM 尝试修改这种格式时,往往很难一边维持 JSON 结构正确,一边完成有意义的内容更新。结果就是笔记本损坏,既打不开,也无法运行。

单元标记的关键作用

创建一个名为 main.py 的文件,先加入第一个单元:

# %%
# 导入所需库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 设置显示选项,便于观察数据
pd.set_option('display.max_columns', None)
plt.style.use('ggplot')

print("数据分析环境已就绪!")

看到顶部的 # %% 了吗?这就是关键标记。Jupyter 扩展会把它识别为一个代码单元。加上这个标记后,你会看到旁边出现运行按钮;只执行这一段,结果就会直接显示在编辑器里。

再添加一个说明单元:

# %% [markdown]
"""
# Iris 数据集分析

这个笔记本会探索经典的 Iris 鸢尾花数据集,重点回答以下问题:
- 不同花朵测量特征之间有什么关系
- 这些特征能否区分不同物种
- 哪些特征最能把不同物种区分开来

数据集中的每一朵花都属于以下三种物种之一:
1. Setosa
2. Versicolor
3. Virginica
"""

这是一种很实用的组合:可执行代码和完整文档共存在同一个纯文本文件里。没有额外文件格式,也没有浏览器编辑的限制,版本控制也更顺手。

在逐步搭建这个 Notebook 时,我们会遵循下面的结构:

  • # %% 表示代码单元
  • # %% [markdown] 加三引号编写说明文本
  • 按照“载入数据、探索数据、可视化数据”的逻辑推进
  • 一边分析,一边把过程和发现记录下来

让 LLM 真正帮上忙:把它当成数据分析助手

真正让这套工作流有价值的,是它和 Cursor Composer 的整合。它不只是自动补全,而更像一个能理解数据分析语境的协作助手。

Agent 模式:让 LLM 真正参与数据分析

在 Cursor IDE 中点击 Composer,然后切换到 Agent 模式。这样会启用一个更完整的 AI 助手,它能够:

  • 在多轮交互中保留上下文
  • 理解你的数据集和分析目标
  • 生成带有正确 Jupyter 语法的完整代码单元
  • 根据你的数据生成合适的可视化

先让它帮我们导入一个数据集:

请按这种笔记本格式导入 Iris 数据集

AI 会生成一个完整、可执行的单元:

# %%
# 导入所需库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris

# 载入 Iris 数据集
iris = load_iris()

# 转换为 pandas DataFrame
df = pd.DataFrame(data=iris.data, columns=iris.feature_names)
df['species'] = iris.target

# 查看前几行
print(df.head())

只用一句简单提示词,我们就得到一个格式正确、可直接运行的代码单元。函数名、导入方式和整体结构都不需要再自己硬记,AI 会先帮你搭好。

但真正能看出效果的,是让它直接生成可视化:

请为 Iris 数据集生成一个三维散点图,用不同颜色表示三种物种

AI 会创建一个带有旋转效果的复杂 3D 可视化:

展示 Iris 数据集聚类分布的 3D 散点图

# %%
# 创建 3D 散点图
from mpl_toolkits.mplot3d import Axes3D

# 创建图形和 3D 坐标轴
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')

# 获取三种物种名称
species_names = iris.target_names
colors = ['blue', 'red', 'green']

# 为每个物种使用不同颜色绘图
for species_id, species_name in enumerate(species_names):
    # 筛选当前物种的数据
    species_data = df[df['species'] == species_id]
    
    # 绘制当前物种
    ax.scatter(
        species_data['sepal length (cm)'],
        species_data['sepal width (cm)'],
        species_data['petal length (cm)'],
        c=colors[species_id],
        label=species_name,
        s=60,
        alpha=0.8
    )

# 设置标签和标题
ax.set_xlabel('Sepal Length (cm)')
ax.set_ylabel('Sepal Width (cm)')
ax.set_zlabel('Petal Length (cm)')
ax.set_title('3D Scatter Plot of Iris Dataset')
ax.legend()

# 添加旋转效果,便于观察
for angle in range(0, 360, 5):
    ax.view_init(30, angle)
    plt.draw()
    plt.pause(0.001)

plt.show()

这已经不只是“画一张图”了,而是一张会旋转、能从多个角度观察数据的 3D 可视化,标签、颜色和格式也都处理妥当,而且只来自一句提示词。

用 Cursor 规则引导 LLM 生成更贴合习惯的代码

我后来发现,还可以在项目根目录创建一个 .cursorrules 文件,让 AI 生成的代码更贴近自己的习惯。这个文件里放的是自定义说明,用来约束 AI 该如何写代码。

如果你想系统了解如何配置和使用 Cursor 规则,可以参考我另一篇更详细的文章:如何用 Cursor 规则优化 AI 编码体验

例如,我加入了这些规则:

<cursorrules_code_style>
- Prefer functional programming over OOP
- Use pure functions with clear input/output
- Use strict typing for all variables and functions
</cursorrules_code_style>

<cursorrules_python_specifics>
- Prefer Pydantic over TypedDict for data models
- Use pyproject.toml over requirements.txt
- For complex structures, avoid generic collections
</cursorrules_python_specifics>

加上这些规则后,AI 开始稳定生成符合我偏好的类型安全代码:

# %%
# 定义 Pydantic 模型,增强类型安全
from pydantic import BaseModel
from typing import List, Optional

class IrisFeatures(BaseModel):
    sepal_length: float
    sepal_width: float
    petal_length: float
    petal_width: float
    species: int
    species_name: Optional[str] = None

# 将 DataFrame 行转换为 Pydantic 模型
def convert_to_models(df: pd.DataFrame) -> List[IrisFeatures]:
    species_map = {0: "setosa", 1: "versicolor", 2: "virginica"}
    
    return [
        IrisFeatures(
            sepal_length=row["sepal length (cm)"],
            sepal_width=row["sepal width (cm)"],
            petal_length=row["petal length (cm)"],
            petal_width=row["petal width (cm)"],
            species=row["species"],
            species_name=species_map[row["species"]]
        )
        for _, row in df.iterrows()
    ]

# 转换一个样本做演示
iris_models = convert_to_models(df.head())
for model in iris_models:
    print(model)

AI 基本会按这些规则来生成代码,产出的结果类型更明确,也更接近我平时偏好的函数式写法和数据模型风格。

用 Python 探索 Iris 数据集:开始真正做分析

环境已经搭好,AI 助手也准备就绪,现在可以正式开始探索经典的 Iris 数据集了。

先看一眼数据

数据已经载入,但我们先看看它的整体结构:

# %%
# 获取数据集的基础信息
print("Dataset shape:", df.shape)
print("\nClass distribution:")
print(df['species'].value_counts())

# 创建一个更易读的物种名称列
species_names = {0: 'setosa', 1: 'versicolor', 2: 'virginica'}
df['species_name'] = df['species'].map(species_names)

# 显示描述性统计
print("\nDescriptive statistics:")
print(df.describe())

从这里可以看出,我们有 150 个样本,每个物种各 50 个,一共 4 个描述花朵不同部位的特征。接着,再用箱线图看看这些特征在不同物种之间是怎么变化的:

# %%
# 为每个特征按物种绘制箱线图
plt.figure(figsize=(12, 10))

for i, feature in enumerate(iris.feature_names):
    plt.subplot(2, 2, i+1)
    sns.boxplot(x='species_name', y=feature, data=df)
    plt.title(f'Distribution of {feature} by Species')
    plt.xticks(rotation=45)

plt.tight_layout()
plt.show()

这些箱线图会揭示一些很直观的模式。Setosa 的花萼明显更宽,但花瓣较小;Virginica 的花瓣整体最大。不过,究竟哪些特征最能把不同物种区分开?

找出隐藏模式

为了回答这个问题,我们需要看特征之间的关系:

# %%
# 绘制 pairplot,查看特征之间的关系
sns.pairplot(df, hue='species_name', height=2.5)
plt.suptitle('Iris Dataset Pairwise Relationships', y=1.02)
plt.show()

这个 pairplot 很有启发性。它把所有特征的两两组合都画了出来,并按照物种着色。我们几乎可以立刻看出:

  1. 只要图里包含花瓣测量值,Setosa(蓝色)就会和另外两种完全分开
  2. Versicolor 和 Virginica 有一定重叠,但仍然可以区分
  3. 花瓣长度和花瓣宽度最能清楚地区分三种物种

但最醒目的图,还是前面那个 3D 散点图。随着图像旋转到不同角度,会出现几个视角,让三种物种的聚类几乎完全分离,这种洞察在静态二维图里很难直接看出来。

如果你想进一步学习更高级的可视化和数据分析技巧,可以参考内容很扎实的 scikit-learn User Guide

解决 Jupyter 集成中的障碍:排查依赖问题

再顺的工作流,也总会遇到问题。等我开始尝试更复杂的可视化时,就碰到了一次 Seaborn 导入错误:

ImportError: Seaborn not valid package style

这类问题在数据分析环境里很常见,本质上通常是包版本不兼容。为了定位问题,我加了一个单元来检查当前安装的版本:

# %%
# 检查已安装依赖的版本
import pkg_resources
print("Installed packages:")
for package in ['numpy', 'pandas', 'matplotlib', 'seaborn', 'scikit-learn']:
    try:
        version = pkg_resources.get_distribution(package).version
        print(f"{package}: {version}")
    except pkg_resources.DistributionNotFound:
        print(f"{package}: Not installed")

最后我发现,是 Seaborn 的版本和 NumPy 版本不兼容。解决办法是利用 Cursor 的弹出终端功能:

  1. 点击底部面板里的终端图标
  2. 选择 Pop out terminal
  3. 运行更新命令:
    pip install seaborn --upgrade
    

这正是 Cursor IDE 发挥优势的地方。我不需要切换工具,也不用离开当前分析上下文,就能把依赖问题修好。

更进一步说,我还可以直接把错误信息发给 AI,它会建议出准确的修复命令。弹出终端配合 AI 辅助,排障会比传统环境快很多。

让数据可视化真正帮助理解模式:在 Jupyter 中制作交互图表

环境顺起来之后,我想做的不只是“把图画出来”,而是让图真正帮助我理解数据里的模式。

从简单图表到 3D 可视化

我先从一个关注花瓣尺寸的简单散点图开始:

# %%
# 绘制花瓣尺寸散点图
plt.figure(figsize=(10, 6))
for species_id, species_name in enumerate(iris.target_names):
    species_data = df[df['species'] == species_id]
    plt.scatter(
        species_data['petal length (cm)'],
        species_data['petal width (cm)'],
        label=species_name,
        alpha=0.7,
        s=70
    )

plt.title('Petal Dimensions by Species')
plt.xlabel('Petal Length (cm)')
plt.ylabel('Petal Width (cm)')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

这个图会立刻显示出,Setosa 在左下角形成了一个很紧的簇,花瓣测量值和另外两种物种明显不同。

为了更深入理解这些关系,我又做了一个相关性热力图:

# %%
# 计算相关系数矩阵
correlation_matrix = df.drop(columns=['species_name']).corr()

# 绘制热力图
plt.figure(figsize=(10, 8))
sns.heatmap(
    correlation_matrix, 
    annot=True,
    cmap='coolwarm',
    linewidths=0.5,
    vmin=-1, 
    vmax=1
)
plt.title('Correlation Matrix of Iris Features')
plt.show()

热力图显示,花瓣长度和花瓣宽度之间存在非常强的相关性,相关系数达到 0.96。换句话说,这两个特征往往会一起变化。

不过,最令人印象深刻的还是前面那个带旋转效果的 3D 散点图。随着视角变化,会出现一些瞬间,让三种物种几乎完全分离,揭示出静态二维图里很难捕捉到的模式。

这就是交互式数据可视化的价值。它能把抽象数字转化为更直观、更容易形成判断的观察结果。

分享分析结果:从探索到展示

在挖出这些洞察之后,我需要把结果分享给那些没有安装 Python 或 Jupyter 的同事。这时,Jupyter 扩展的导出能力就变得非常关键。

制作专业报告

为了生成一份可分享的报告:

  1. 我先确认所有单元都执行过,保证输出完整可见
  2. 添加说明单元,解释方法和结论
  3. 使用 Jupyter 扩展里的 Export as HTML
  4. 在浏览器中打开 HTML 文件,再用 Save as PDF 生成更正式的文档

将 Jupyter 笔记本导出为专业 PDF 报告

最终得到的报告会包含全部代码、说明文字和可视化内容,而且任何人都可以打开查看。前面在 Markdown 排版上的细心处理也会在这里得到回报,因为标题、项目符号和强调样式都能较好地保留到最终文档中。

如果要把报告展示给非技术背景的受众,我通常会把图表尺寸调到更适合展示的规格,例如:

plt.figure(figsize=(10, 6), dpi=300)

这样可以保证图表在导出的 PDF 里依然清晰、易读。

对于 3D 可视化,我会在导出之前把视角停在最能传达信息的角度,因为旋转动画最终会被导出为一张静态图。只要角度选得好,报告就能准确突出我想强调的模式。

工作流的变化:在 Cursor IDE 中做 LLM 加持的数据分析

回头看整个过程,这种变化很明显。过去需要三套工具、不断切换上下文才能完成的工作,现在可以在一个环境里顺畅做完。我的流程变成了:

  1. 探索: 用 AI 帮忙载入数据并生成初步可视化
  2. 发现: 利用 Jupyter 的按单元执行方式交互式细化分析
  3. 记录: 通过说明单元把结论直接写在代码旁边
  4. 分享: 用一条命令把完整分析导出为专业报告

Jupyter 的交互性、Cursor IDE 的编辑能力,以及 AI 辅助结合在一起,消除了过去那些不断打断专注的摩擦。我终于可以顺着自己的问题往前追,而不是不停为工具切换付出额外代价。

还有一个意料之外的好处:因为我用的是纯文本文件,而不是原始的 Jupyter Notebook 格式,整个分析流程终于能被 Git 好好管理。我可以清楚看到每个版本到底改了什么,和团队协作时也更不容易陷入合并冲突。

这不只是节省时间而已,它也改变了我做数据分析的方式。没有那些频繁的上下文切换之后,我更容易保持专注,也更容易沿着一个发现继续深入。分析会更完整,文档会更充分,可视化也会更有效。

如果你已经厌倦了为数据分析工作同时维护多个工具,我建议你试试这种一体化方法:在 Cursor IDE 中配置好 Jupyter,用上 AI 助手,亲自体验统一工作流带来的变化。未来某个凌晨两点的你,可能会感谢现在的自己。

对比:传统 Jupyter 与 LLM 增强的 Cursor IDE

下面这张表可以快速总结传统 Jupyter Notebook 方法和 Cursor IDE 中纯文本 Jupyter 工作流之间的关键差异:

对比项传统 Jupyter 笔记本Cursor IDE + 纯文本 Jupyter
文件格式复杂 JSON(.ipynb纯文本 Python(.py
版本控制困难,diff 大且容易产生合并冲突很好,可直接融入标准 Git 工作流
IDE 能力代码导航与重构能力有限拥有完整 IDE 能力,如搜索、替换与跳转
AI 辅助有限LLM 集成更强,并具备上下文感知能力
单元执行依赖浏览器界面原生 IDE 环境
上下文切换做复杂编辑时不可避免所有事情都能在一个环境里完成
性能大型笔记本时可能变慢受益于原生编辑器性能
调试调试能力有限拥有完整的 IDE 调试工具
导出选项HTML、PDF 等多种格式通过扩展提供同样能力
协作与版本控制结合时比较困难符合标准代码协作流程
依赖管理通常分散在单独的环境文件中环境管理可直接整合进项目
隐藏状态问题乱序执行时很常见因鼓励线性执行而有所减少
Markdown 支持原生支持通过单元标记获得同等能力
类型检查没有具备完整 IDE 静态分析支持
扩展生态Jupyter 扩展IDE 扩展 + Jupyter 扩展

这张对比表已经很清楚地说明了,为什么 Cursor IDE 这种做法对认真做数据分析的人更有优势,尤其是在你想利用 AI 能力、又想保持工作流顺畅的时候。

如果你想更深入了解 Jupyter 的架构和能力,可以继续阅读 Project Jupyter Documentation

视频教程:完整观看 Cursor IDE 中的 Jupyter 工作流

如果你更喜欢通过视频学习,我也制作了一份完整教程,逐步演示本文涉及的所有内容:

在 Cursor IDE 中使用 Jupyter Notebook 的视频教程

视频会完整展示如何在 Cursor IDE 中设置并使用 Jupyter Notebook、AI 集成是如何工作的、如何创建可视化,以及如何导出结果。整个过程都在同一个环境里完成,而这正是这套工作流最有价值的地方。

Artículos Relacionados

[zh]
[Article]
那些一边拆解自己手艺一边继续创作的人:从喜剧演员、管理者到工程师的自嘲、自动化与自我淘汰的共同模式解析

那些一边拆解自己手艺一边继续创作的人:从喜剧演员、管理者到工程师的自嘲、自动化与自我淘汰的共同模式解析

这篇文章梳理一种反复出现的创作冲动:喜剧演员拆解喜剧,管理者建立不依赖自己的系统,工程师用 AI 自动化自己的工作。作者借这些例子讨论,为什么人会主动削弱自身的重要性,以及这种自我拆解为何反而可能让作品、团队和职业判断更有价值。它关注的不是口号式反技术,而是熟悉这门手艺的人,如何亲手把自己变得没那么必要。

[zh]
[Article]
Cursor IDE 的 AI 规则:我长期使用的一套更稳、更一致的编码、审查、协作与提交流程规则集

Cursor IDE 的 AI 规则:我长期使用的一套更稳、更一致的编码、审查、协作与提交流程规则集

分享我在 Cursor IDE 中长期使用的一套全局 AI 规则,以及它如何与仓库级规则和按上下文触发的规则配合,帮助 AI 在代码风格、类型约束、错误处理、依赖管理和开发流程上持续输出更稳定、更一致的结果,减少返工,也让个人项目和团队协作里的 AI 输出保持同一水准,并减少沟通成本。

[zh]
[Article]
我如何用 AI 管理银行流水、支出分类、账户余额和滚动 12 个月预算,并判断大额消费何时发生更合适

我如何用 AI 管理银行流水、支出分类、账户余额和滚动 12 个月预算,并判断大额消费何时发生更合适

这篇文章写我如何用 AI 整理银行流水、自动分类记账、核对多个账户余额,并维护一份滚动 12 个月预算,用来判断现金流是否稳健、多币种收支怎样归类,以及旅行、家具或其他大额支出到底该不该现在发生,也让我能更早发现预算里的危险月份并调整计划,还更方便比较不同账户和月份之间的变化趋势。

作者简介

Kirill Markin

Kirill Markin

首席技术官

ozma.io 前创始人

人工智能与数据工程师

9,500+
subscribers

Compartir este artículo