一图胜千言|图解Pandas常用操作!

图解大语言模型:从Transformer到RAG与Agent的认知图谱构建 Transformer架构作为现代大语言模型的核心,通过自注意力机制实现了对序列数据的并行处理和长距离依赖建模,奠定了生成式AI的技术基础。其工程价值在于能够高效捕捉文本中的复杂语义关系,支撑了从文本生成到代码编写的广泛应用。基于此,检索增强生成(RAG)技术通过结合外部知识库与生成模型,有效缓解了模型幻觉问题,提升了回答的准确性与时效性。而AI Agent则进一步赋予大语言模型规划与执行能力,通过工具调用和工作流编排,实现了复杂任务的自动化处理。本文将以图解方式,系统构建从模型内部机制到外部应用架构的完整 阅读详情
👇我的小册 45章教程:(小白零基础用Python量化股票分析小册) ,原价299,限时特价2杯咖啡,满100人涨10元。

来源:网络

Pandas 展示

请看下表:

2e39a212fa37de9ed7a38ed622bfbf67.png

它描述了一个在线商店的不同产品线,共有四种不同的产品。与前面的例子不同,它可以用NumPy数组或Pandas DataFrame表示。但让我们看一下它的一些常见操作。

1. 排序

使用Pandas按列排序更具可读性,如下所示:

78de93899b197f1f470bd21f0a7b6c3d.png

这里argsort(a[:,1])计算使a的第二列按升序排序的排列,然后a[…]相应地对a的行重新排序。Pandas可以一步完成。

2.按多列排序

如果我们需要使用weight列来对价格列进行排序,情况会变得更糟。这里有几个例子来说明我们的观点:

62f98ec72a045db0db07dd4b9cac65ee.png

在NumPy中,我们先按重量排序,然后再按价格排序。稳定排序算法保证第一次排序的结果不会在第二次排序期间丢失。NumPy还有其他实现方法,但没有一种方法像Pandas那样简单优雅。

3. 添加一列

使用Pandas添加列在语法和架构上要好得多。下面的例子展示了如何操作:

bda2ec48ed86821ed39a514eaf54b016.png

Pandas不需要像NumPy那样为整个数组重新分配内存;它只是添加了对新列的引用,并更新了列名的` registry `。

4. 快速元素搜索

在NumPy数组中,即使你查找的是第一个元素,你仍然需要与数组大小成正比的时间来查找它。使用Pandas,你可以索引你期望被查询最多的列,并将搜索时间减少到一个常量。

0bca7da1a3ba4b4d0d71dcb26ecfb964.png

index列有以下限制。

  • 它需要内存和时间来构建。

  • 它是只读的(需要在每次追加或删除操作后重新构建)。

  • 这些值不需要是唯一的,但是只有当元素是唯一的时候加速才会发生。

  • 它需要预热:第一次查询比NumPy稍慢,但后续查询明显快得多。

5. 按列连接(join)

如果你想从另一张表中获取基于同一列的信息,NumPy几乎没有任何帮助。Pandas更好,特别是对于1:n的关系。

0769f64acfad20ce784ad747e39ffaa4.png

Pandas join具有所有熟悉的“内”、“左”、“右”和“全外部”连接模式。

按列分组

数据分析中的另一个常见操作是按列分组。例如,要获得每种产品的总销量,你可以这样做:

2942142721697ddddb71c175cedd42a0.png

除了sum之外,Pandas还支持各种聚合函数:mean、max、min、count等。

7. 数据透视表

Pandas最强大的功能之一是“枢轴”表。这有点像将多维空间投影到二维平面上。

55537507ee6e2625eb884f7012819857.png

虽然用NumPy当然可以实现它,但这个功能没有开箱即用,尽管它存在于所有主要的关系数据库和电子表格应用程序(Excel,WPS)中。

Pandas用df.pivot_table将分组和旋转结合在一个工具中。

简而言之,NumPy和Pandas的两个主要区别如下:

83ee89f80755d5b8521cad0bdb2e773d.png

现在,让我们看看这些功能是否以性能损失为代价。

Pandas速度

我在Pandas的典型工作负载上对NumPy和Pandas进行了基准测试:5-100列,10³- 10⁸行,整数和浮点数。下面是1行和1亿行的结果:

54a12bf0d60c20c09ead7da5fbd1536b.png

看起来在每一次操作中,Pandas都比NumPy慢!

当列数增加时,情况不会改变(可以预见)。至于行数,依赖关系(在对数尺度下)如下所示:

5f093c6a75394f56002fa3bb38da39c8.png

对于小数组(少于100行),Pandas似乎比NumPy慢30倍,对于大数组(超过100万行)则慢3倍。

怎么可能呢?也许是时候提交一个功能请求,建议Pandas通过df.column.values.sum()重新实现df.column.sum()了?这里的values属性提供了访问底层NumPy数组的方法,性能提升了3 ~ 30倍。

答案是否定的。Pandas在这些基本操作方面非常缓慢,因为它正确地处理了缺失值。Pandas需要NaNs (not-a-number)来实现所有这些类似数据库的机制,比如分组和旋转,而且这在现实世界中是很常见的。在Pandas中,我们做了大量工作来统一所有支持的数据类型对NaN的使用。根据定义(在CPU级别上强制执行),nan+anything会得到nan。所以

>>> np.sum([1, np.nan, 2])
nan

但是

>>> pd.Series([1, np.nan, 2]).sum()
3.0

一个公平的比较是使用np.nansum代替np.sum,用np.nanmean而不是np.mean等等。突然间……

481fa4f7da233383d38febf58a3f2c8f.png

对于超过100万个元素的数组,Pandas的速度是NumPy的1.5倍。对于较小的数组,它仍然比NumPy慢15倍,但通常情况下,无论操作在0.5 ms还是0.05 ms内完成都没有太大关系——无论如何它都是快速的。

最重要的是,如果您100%确定列中没有缺失值,则使用df.column.values.sum()而不是df.column.sum()可以获得x3-x30的性能提升。在存在缺失值的情况下,Pandas的速度相当不错,甚至在巨大的数组(超过10个同质元素)方面优于NumPy。

第二部分. Series 和 Index

0afbd4f1582908d635f4fdd75d23b53f.png

Series是NumPy中的一维数组,是表示其列的DataFrame的基本组成部分。尽管与DataFrame相比,它的实际重要性正在降低(你可以在不知道Series是什么的情况下完美地解决许多实际问题),但如果不首先学习Series和Index,你可能很难理解DataFrame是如何工作的。

在内部,Series将值存储在普通的NumPy vector中。因此,它继承了它的优点(紧凑的内存布局、快速的随机访问)和缺点(类型同质、缓慢的删除和插入)。最重要的是,Series允许使用类似于字典的结构index通过label访问它的值。标签可以是任何类型(通常是字符串和时间戳)。它们不必是唯一的,但唯一性是提高查找速度所必需的,许多操作都假定唯一性。

1c412efd7558f7b6aa66aec90e4a51fd.png

如你所见,现在每个元素都可以通过两种替代方式寻址:通过` label `(=使用索引)和通过` position `(=不使用索引):

fd40474982d354f20dc17e58e601e7fe.png

按“位置”寻址有时被称为“位置索引”,这只是增加了混淆。

一对方括号是不够的。特别是:

  • S[2:3]不是解决元素2最方便的方式

  • 如果名称恰好是整数,s[1:3]就会产生歧义。它可能意味着名称1到3包含或位置索引1到3不包含。

为了解决这些问题,Pandas还有两种“风格”的方括号,你可以在下面看到:

f52f4d699b37cebb444424227f2a0416.png

.loc总是使用标号,并且包含间隔的两端。

.iloc总是使用“位置索引”并排除右端。

使用方括号而不是圆括号的目的是为了访问Python的切片约定:你可以使用单个或双冒号,其含义是熟悉的start:stop:step。像往常一样,缺少开始(结束)意味着从序列的开始(到结束)。step参数允许使用s.iloc[::2]引用偶数行,并使用s['Paris':'Oslo':-1]以相反的顺序获取元素。

它们还支持布尔索引(使用布尔数组进行索引),如下图所示:

fbdc9ed186f2a6763f0439f421863c75.png

你可以在下图中看到它们如何支持` fancy indexing `(用整数数组进行索引):

f934910f9a06a26333ba679c82ccf534.png

Series最糟糕的地方在于它的视觉表现:出于某种原因,它没有一个很好的富文本外观,所以与DataFrame相比,它感觉像是二等公民:

5ce8f9197eb9c557f2ef887419bca31a.png

我对这个Series做了补丁,让它看起来更好,如下所示:

0da8f5e9b5fb10fc5952d0933ffe5f84.png

垂直线表示这是一个Series,而不是一个DataFrame。Footer在这里被禁用了,但它可以用于显示dtype,特别是分类类型。

您还可以使用pdi.sidebyside(obj1, obj2,…)并排显示多个Series或dataframe:

e783cc29fc709052ad56de7be28fb913.png

pdi(代表pandas illustrated)是github上的一个开源库,具有本文所需的这个和其他功能。要使用它,就要写

pip install pandas-illustrated

索引(Index)

负责通过标签获取元素的对象称为index。它非常快:无论你有5行还是50亿行,你都可以在常量时间内获取一行数据。

指数是一个真正的多态生物。默认情况下,当创建一个没有索引的序列(或DataFrame)时,它会初始化为一个惰性对象,类似于Python的range()。和range一样,几乎不使用任何内存,并且与位置索引无法区分。让我们用下面的代码创建一个包含一百万个元素的序列:

>>> s = pd.Series(np.zeros(10**6))
>>> s.index
RangeIndex(start=0, stop=1000000, step=1)
>>> s.index.memory_usage()       # in bytes
128                    # the same as for Series([0.])

现在,如果我们删除一个元素,索引隐式地转换为类似于dict的结构,如下所示:

>>> s.drop(1, inplace=True)
>>> s.index
Int64Index([     0,      2,      3,      4,      5,      6,      7,
            ...
            999993, 999994, 999995, 999996, 999997, 999998, 999999],
           dtype='int64', length=999999)
>>> s.index.memory_usage()
7999992

该结构消耗8Mb内存!为了摆脱它,回到轻量级的类range结构,添加如下代码:

>>> s.reset_index(drop=True, inplace=True)
>>> s.index
RangeIndex(start=0, stop=999999, step=1)
>>> s.index.memory_usage()
128

如果你不熟悉Pandas,你可能想知道为什么Pandas自己没有做到这一点?好吧,对于非数字标签,有一点很明显:为什么(以及如何)Pandas在删除一行后,会重新标记所有后续的行?对于数值型标签,答案就有点复杂了。

首先,正如我们已经看到的,Pandas允许您纯粹按位置引用行,因此,如果您想在删除第3行之后定位第5行,则可以无需重新索引(这就是iloc的作用)。

其次,保留原始标签是一种与过去时刻保持联系的方法,就像“保存游戏”按钮一样。假设您有一个100x1000000的大表,需要查找一些数据。你正在一个接一个地进行几次查询,每次都缩小了搜索范围,但只查看了一小部分列,因为同时查看数百个字段是不切实际的。现在您已经找到感兴趣的行,您希望在原始表中查看有关它们的所有信息。数字索引可以帮助您立即获得它,而无需任何额外的努力。

一般来说,在索引中保持值的唯一性是一个好主意。例如,在索引中存在重复值时,查找速度不会得到提升。Pandas不像关系型数据库那样有“唯一约束”(该功能仍然是实验性的),但它有检查索引中的值是否唯一的函数,并以各种方式消除重复。

有时,一列不足以唯一标识一行。例如,同一个名字的城市有时会碰巧出现在不同的国家,甚至是同一个国家的不同地区。所以(城市,州)是一个比城市更好的标识一个地方的候选者。在数据库中,这被称为“复合主键”。在Pandas中,它被称为多索引(参见下面的第4部分),索引中的每一列都被称为“级别”。

索引的另一个重要特性是不可变。与DataFrame中的普通列不同,你不能就地更改它。索引中的任何更改都涉及从旧索引中获取数据,修改它,并将新数据作为新索引重新附加。通常情况下,它是透明的,这就是为什么不能直接写df.City.name = ' city ',而必须写一个不那么明显的df.rename(columns={' A ': ' A '}, inplace=True)

Index有一个名称(在MultiIndex的情况下,每个级别都有一个名称)。不幸的是,这个名称在Pandas中没有得到充分使用。一旦你在索引中包含了这一列,就不能再使用df了。不再使用列名表示法,并且必须恢复为可读性较差的df。指数还是更通用的df。loc对于多索引,情况更糟。一个明显的例外是df。Merge -你可以通过名称指定要合并的列,无论它是否在索引中。

同样的索引机制用于标记dataframe的行和列,以及序列。

按值查找元素

Series内部由一个NumPy数组和一个类似数组的结构index组成,如下所示:

1eb4e3307377a729d3c96b0a82eb9af7.png

Index提供了一种通过标签查找值的方便方法。那么如何通过值查找标签呢?

s.index[s.tolist().find(x)]           # faster for len(s) < 1000
s.index[np.where(s.values==x)[0][0]]  # faster for len(s) > 1000

我编写了find()和findall()两个简单的封装器,它们运行速度快(因为它们会根据序列的大小自动选择实际的命令),而且使用起来更方便。代码如下所示:

>>> import pdi
>>> pdi.find(s, 2)
'penguin'
>>> pdi.findall(s, 4)
Index(['cat', 'dog'], dtype='object')

缺失值

Pandas开发人员特别关注缺失值。通常,你通过向read_csv提供一个标志来接收一个带有NaNs的dataframe。否则,可以在构造函数或赋值运算符中使用None(尽管不同数据类型的实现略有不同,但它仍然有效)。这张图片有助于解释这个概念:

101aa15ab6c5a9925e0cb0894116be18.png

你可以使用NaNs做的第一件事是了解你是否有NaNs。从上图可以看出,isna()生成了一个布尔数组,而.sum()给出了缺失值的总数。

现在你知道了它们的存在,你可以选择用常量值填充它们或通过插值来一次性删除它们,如下所示:

e9eb1d18d4f496c7348354a794cd8316.png

另一方面,你可以继续使用它们。大多数Pandas函数会很高兴地忽略缺失值,如下图所示:

bd92376682e502b46b8b2db6896b16ed.png

更高级的函数(median、rank、quantile等)也可以做到这一点。

算术运算与索引对齐:

158239bcfddd531fa233380678e8a8cf.png

如果索引中存在非唯一值,则结果不一致。不要对索引不唯一的序列使用算术运算。

比较

比较有缺失值的数组可能会比较棘手。下面是一个例子:

>>> np.all(pd.Series([1., None, 3.]) == 
           pd.Series([1., None, 3.]))
False
>>> np.all(pd.Series([1, None, 3], dtype='Int64') == 
           pd.Series([1, None, 3], dtype='Int64'))
True
>>> np.all(pd.Series(['a', None, 'c']) == 
           pd.Series(['a', None, 'c']))
False

为了正确地比较nan,需要用数组中一定没有的元素替换nan。例如,使用-1或∞:

>>> np.all(s1.fillna(np.inf) == s2.fillna(np.inf))   # works for all dtypes
True

或者,更好的做法是使用NumPy或Pandas的标准比较函数:

>>> s = pd.Series([1., None, 3.])
>>> np.array_equal(s.values, s.values, equal_nan=True)
True
>>> len(s.compare(s)) == 0
True

这里,compare函数返回一个差异列表(实际上是一个DataFrame), array_equal则直接返回一个布尔值。

当比较混合类型的DataFrames时,NumPy比较失败(issue #19205),而Pandas工作得很好。如下所示:

>>> df = pd.DataFrame({'a': [1., None, 3.], 'b': ['x', None, 'z']})
>>> np.array_equal(df.values, df.values, equal_nan=True)
TypeError
<...>
>>> len(df.compare(df)) == 0
True

追加、插入、删除

虽然Series对象被认为是size不可变的,但它可以在原地追加、插入和删除元素,但所有这些操作都是:

  • 慢,因为它们需要为整个对象重新分配内存和更新索引。

  • 非常不方便。

下面是插入值的一种方式和删除值的两种方式:

b09531fd780017d8e41dcdb0033061f2.png

第二种删除值的方法(通过drop)比较慢,并且在索引中存在非唯一值时可能会导致复杂的错误。

Pandas有df.insert方法,但它只能将列(而不是行)插入到dataframe中(并且对series不起作用)。

添加和插入的另一种方法是使用iloc对DataFrame进行切片,应用必要的转换,然后使用concat将其放回。我实现了一个名为insert的函数,可以自动执行这个过程:

009ddca4acf293914440f8613e245bfd.png

注意(就像在df.insert中一样)插入位置由位置0<=i<=len(s)指定,而不是索引中元素的标签。如下所示:

f03be88866581911dd8c5a0b271795e5.png

要按元素的名称插入,可以合并pdi。用pdi查找。插入,如下所示:

4004c57d740f061259d6f689965c938e.png

请注意,unlikedf.insert、pdi.insert返回一个副本,而不是原地修改Series/DataFrame

统计数据

Pandas提供了全方位的统计函数。它们可以让您了解百万元素序列或DataFrame中的内容,而无需手动滚动数据。

所有Pandas统计函数都会忽略NaNs,如下所示:

19e7ea7191e35509d25222f6e3346915.png

注意,Pandas std给出的结果与NumPy std不同,如下所示:

>>> pd.Series([1, 2]).std()
0.7071067811865476
>>> pd.Series([1, 2]).values.std()
0.5

这是因为NumPy std默认使用N作为分母,而Pandas std默认使用N-1作为分母。两个std都有一个名为ddof (` delta degrees of freedom `)的参数,NumPy默认为0,Pandas默认为1,这可以使结果一致。N-1是你通常想要的值(在均值未知的情况下估计样本的偏差)。这里有一篇维基百科的文章详细介绍了贝塞尔的修正。

由于序列中的每个元素都可以通过标签或位置索引访问,因此argmin (argmax)有一个姐妹函数idxmin (idxmax),如下图所示:

0f741534197f9bc316c1e38c3e94ca40.png

下面是Pandas的自描述统计函数供参考:

  • std:样本标准差

  • var,无偏方差

  • sem,均值的无偏标准误差

  • quantile分位数,样本分位数(s.quantile(0.5)≈s.median())

  • oode是出现频率最高的值

  • 默认为Nlargest和nsmallest,按出现顺序排列

  • diff,第一个离散差分

  • cumsum 和 cumprod、cumulative sum和product

  • cummin和cummax,累积最小值和最大值

以及一些更专业的统计函数:

  • pct_change,当前元素与前一个元素之间的变化百分比

  • skew偏态,无偏态(三阶矩)

  • kurt或kurtosis,无偏峰度(四阶矩)

  • cov、corr和autocorr、协方差、相关和自相关

  • rolling滚动窗口、加权窗口和指数加权窗口

重复数据

在检测和处理重复数据时需要特别小心,如下图所示:

98fb59cef92e144723c5129281c6f896.png

drop_duplicates和duplication可以保留最后一次出现的副本,而不是第一次出现的副本。

请注意,s.a uint()比np快。唯一性(O(N) vs O(NlogN)),它会保留顺序,而不会返回排序结果。独特的。

缺失值被视为普通值,有时可能会导致令人惊讶的结果。

01cb7ae3678f25090120fc03b633521a.png

如果你想排除nan,需要显式地这样做。在这个例子中,是s.l opdropna().is_unique == True。

还有一类单调函数,它们的名字是自描述的:

  • s.is_monotonic_increasing ()

  • s.is_monotonic_decreasing ()

  • s._strict_monotonic_increasing ()

  • s._string_monotonic_decreasing ()

  • s.is_monotonic()。这是意料之外的,出于某种原因,这是s.is_monotonic_increasing()。它只对单调递减序列返回False。

分组

在数据处理中,一个常见的操作是计算一些统计量,不是针对整个数据集,而是针对其中的某些组。第一步是通过提供将一系列(或一个dataframe)分解为组的标准来定义一个“智能对象”。这个`智能对象`没有立即的表示,但可以像Series一样查询它,以获得每个组的某个属性,如下图所示:

8a05f9688f4217e7dcb5205e71850ed5.png

在这个例子中,我们根据数值除以10的整数部分将序列分成三组。对于每个组,我们请求每个组中元素的和、元素的数量以及平均值。

除了这些聚合函数,您还可以根据特定元素在组中的位置或相对值访问它们。如下所示:

92f43ef9f082202b41542bb34006153b.png

你也可以使用g.ag (['min', 'max'])一次调用计算多个函数,或者使用g.c describe()一次显示一堆统计函数。

如果这些还不够,你还可以通过自己的Python函数传递数据。它可以是:

一个函数f,它接受一个组x(一个Series对象)并生成一个值(例如sum())与g.eapply (f)一起使用。

一个函数f,它接受一个组x(一个Series对象),并与g.transform(f)生成一个大小与x相同的Series对象(例如cumsum())。

d79130b1b79f6ac5961c56f237f66d88.png

在上面的例子中,输入数据是有序的。groupby不需要这样做。实际上,如果分组中的元素不是连续存储的,它也同样有效,因此它更接近于collections.defaultdict,而不是itertools.groupby。它总是返回一个没有重复项的索引。

a924646a8bfc783513aa14d8df1318de.png

与defaultdict和关系数据库GROUP BY子句不同,Pandas groupby按组名对结果进行排序。可以用sort=False来禁用它。

免责声明:实际上,g.apply(f)比上面描述的更通用:

  • 如果f(x)返回与x大小相同的序列,它可以模拟transform

  • 如果f(x)返回一系列不同大小或不同的dataframe,则会得到一个具有相应多索引的序列。

但文档警告说,这些使用方法可能比相应的transform和agg方法慢,所以要小心。

第三部分. DataFrames

af38c6f0611085a39f410651b1d39e0f.png

Pandas的主要数据结构是DataFrame。它将一个二维数组与它的行和列的标签捆绑在一起。它由一系列对象组成(具有共享索引),每个对象表示一列,可能具有不同的dtype。

读写CSV文件

构造DataFrame的一种常用方法是读取csv(逗号分隔值)文件,如下图所示:

68f4be1f3597611342f65112e2839a89.png

pd.read_csv()函数是一个完全自动化且可疯狂定制的工具。如果你只想学习Pandas的一件事,那就学习使用read_csv——它会有回报的:)。

下面是一个解析非标准的.csv文件的例子:

b0d548f5439cefec65771aed6bc148a3.png

以及一些简要描述:

398ce28dd3277735bdbecef492e17fb9.png

因为CSV没有严格的规范,所以有时需要一些试错才能正确地阅读它。read_csv最酷的地方在于它会自动检测很多东西:

  • 列名和类型

  • 布尔值的表示

  • 缺失值的表示等。

与其他自动化一样,你最好确保它做了正确的事情。如果在Jupyter单元中简单地编写df的结果碰巧太长(或太不完整),您可以尝试以下操作:

  • df.head(5)或df[:5]显示前5行

  • df.dtypes返回列的类型

  • df.shape返回行数和列数

  • Df.info()汇总所有相关信息

将一列或几列设置为索引是一个好主意。下图展示了这个过程:

c8a7df3eaded77fd5eeffa0ae3d604c4.png

Index在Pandas中有很多用途:

  • 算术运算按索引对齐

  • 它使按该列进行的查找更快,等等。

所有这些都是以较高的内存消耗和不太明显的语法为代价的。

构建DataFrame

另一种选择是从内存中已经存储的数据中构建一个dataframe。它的构造函数非常全能,可以转换(或包装)任何类型的数据:

cd7673883a4c4f27b7552fe19688e933.png

在第一种情况下,在没有行标签的情况下,Pandas用连续的整数标记行。在第二种情况下,它对行和列都进行了相同的操作。为Pandas提供列的名称总是一个好主意,而不是整数标签(使用columns参数),有时也可以提供行(使用index参数,尽管rows听起来可能更直观)。这张图片会有帮助:

f825894c7b09ddcf19e9cf93c73c8bb8.png

不幸的是,无法在DataFrame构造函数中为索引列设置名称,所以唯一的选择是手动指定,例如,df.index.name = '城市名称'

下一种方法是使用NumPy向量组成的字典或二维NumPy数组构造一个DataFrame:

0342e65f383a405c80339cd24c7a9c2b.png

请注意,在第二种情况下,人口数量的值被转换为浮点数。实际上,它在之前的构建NumPy数组时就发生过。这里需要注意的另一件事是,从2D NumPy数组构建dataframe默认是视图。这意味着改变原始数组中的值会改变dataframe,反之亦然。另外,它节省了内存。

第一种情况(NumPy向量组成的字典)也可以启用这种模式,设置copy=False即可。不过,它非常脆弱。简单的操作就可以把它变成副本而不需要通知。

另外两个(不太有用的)创建DataFrame的选项是:

  • 从一个dict列表(其中每个dict表示一行,其键是列名,其值是相应的单元格值)

  • 来自由Series组成的dict(其中每个Series表示一列;默认情况下,可以让它返回一个copy=False的视图)。

如果你“动态”注册流数据,最好的选择是使用列表的dict或列表的列表,因为Python会透明地在列表末尾预分配空间,以便快速追加。NumPy数组和Pandas dataframes都不能做到这一点。另一种可能性(如果你事先知道行数)是用DataFrame(np.zeros)之类的东西手动预分配内存。

DataFrames的基本操作

DataFrame最好的地方(在我看来)是你可以:

  • 轻松访问其列,如d.area返回列值(或者df[' Area ']——适用于包含空格的列名)

  • 将列作为自变量进行操作,例如使用afterdf. population /= 10**6人口以百万计存储,下面的命令根据现有列中的值创建一个名为` density `的新列。更多信息见下图:

6e3f33656464fc69a26dc8da85def811.png

注意,创建新列时,即使列名中不包含空格,也必须使用方括号。

此外,你可以对不同dataframe中的列使用算术操作,只要它们的行具有有意义的标签,如下所示:

47df651535417959b66ccc0fdb883af3.png

索引DataFrames

正如我们在本系列中已经看到的,普通的方括号不足以满足索引的所有需求。你不能通过名称访问行,不能通过位置索引访问不相交的行,你甚至不能引用单个单元格,因为df['x', 'y']是为多索引保留的!

a1765270b0db91be9a3227cb8b682de9.png

为了满足这些需求,dataframes,就像series一样,有两种可选的索引模式:按标签索引的loc和按位置索引的iloc。

07081ff23e2a5ceba619ae4966beb2a8.png

在Pandas中,引用多行/多列是一个副本,而不是视图。但它是一种特殊的复制,允许赋值作为一个整体:

  • df.loc[‘a’]=10 works (一行作为一个整体是一个可写的)

  • df.loc[‘a’][‘A’]=10 works (元素访问传播到原始df)

  • df.loc[‘a’:’b’] = 10 works (assigning to a subar将整个作品赋值给一个子数组)

  • df.loc[‘a’:’b’][‘A’] = 10 doesn’t (对其元素赋值不会).

在最后一种情况下,该值只会被设置在切片的副本上,而不会反映在原始df上(会相应地显示一个警告)。

根据不同的背景,有不同的解决方案:

  1. 你想要改变原始的df。然后使用df。loc[' a': ' b ', ' a'] = 10

  2. 你故意创建了一个副本,然后想要处理这个副本:df1 = df.loc[' a ': ' b '];df1[' A ']=10 # SettingWithCopy warning要在这种情况下消除警告,请使其成为一个真正的副本:df1 = df.loc[' A ': ' b '].copy();df1 [A] = 10

Pandas还支持一种方便的NumPy语法来进行布尔索引。

396660ec672cefeb66811a21f26c38d4.png

当使用多个条件时,必须将它们括起来,如下所示:

f2c28b8fa35deac8b42affaacc3cd193.png

当你期望返回一个值时,需要特别注意。

5bf33fe4870413ba2e54aaff68781f7a.png

因为可能有多行匹配条件,所以loc返回一个序列。要从中得到标量值,你可以使用:

  • float(s)或更通用的s.e item(),除非序列中只有一个值,否则都会引发ValueError

S.iloc[0],仅在没有找到时引发异常;此外,它是唯一支持赋值的函数:df[…].Iloc[0] = 100,但当你想修改所有匹配时,肯定不需要它:df[…]= 100。

或者,你可以使用基于字符串的查询:

  • df.query (' name = =“Vienna”)

df.query('population>1e6 and area<1000')它们更短,适合多索引,并且逻辑操作符优先于比较操作符(=需要更少的括号),但它们只能按行过滤,并且不能通过它们修改Dataframe。

几个第三方库允许你使用SQL语法直接查询dataframe (duckdb),或者通过将dataframe复制到SQLite并将结果包装回Pandas objects (pandasql)来间接查询dataframe。不出所料,直接法更快。

DataFrame算术

你可以对dataframes、series和它们的组合应用普通操作,如加、减、乘、除、求模、幂等。

所有的算术运算都是根据行标签和列标签对齐的:

98a6f02f2ee2ad342fa3ab7174b0f516.png

在dataframe和Series之间的混合操作中,Series(天知道为什么)表现得(和广播)像一个行向量,并相应地对齐:

355480f58a2b08088c074ef3b0f74baf.png

可能是为了与列表和一维NumPy向量保持一致(它们不按标签对齐,并被认为是一个简单的二维NumPy数组的DataFrame):

fe91ebd823038b52ee54ebdc9fee22fc.png

因此,在不太幸运(也是最常见的!)的情况下,将一个dataframe除以列向量序列,你必须使用方法而不是操作符,如下所示:

9f6b06aa267e5ccf71b503a1249cf4b0.png

由于这个有问题的决定,每当你需要在dataframe和列式序列之间执行混合操作时,你必须在文档中查找它(或记住它):

969d4115ce0ef9b54f91393e1aef0788.png

结合DataFrames

Pandas有三个函数,concat、merge和join,它们做同样的事情:将来自多个dataframe的信息合并为一个。但是每个工具的实现方式都略有不同,因为它们是为不同的用例量身定制的。

垂直叠加

这可能是将两个或多个dataframe合并为一个的最简单方法:您获取第一个dataframe中的行,并将第二个dataframe中的行追加到底部。为了使其工作,这两个dataframe需要(大致)具有相同的列。这类似于NumPy中的vstack,正如你在图像中所看到的:

16bf6247a386939705cf8d4b1f6a0233.png

索引中有重复的值是不好的。你可能会遇到各种各样的问题(参见下面的` drop `示例)。即使你不关心索引,也要尽量避免出现重复的值:

  • 要么使用reset_index=True参数

  • 调用df.reset_index(drop=True)将行从0重新索引到len(df)-1,

  • 使用keys参数可以解决MultiIndex的二义性(见下文)。

如果dataframe的列不能完美匹配(不同的顺序在这里不计算在内),Pandas可以取列的交集(默认值kind='inner ')或插入nan来标记缺失值(kind='outer'):

14a6b7c019f0d451c8e8627ad950ab35.png

水平叠加

concat也可以执行“水平”堆叠(类似于NumPy中的hstack):

e4214702da6cba9f970b5270deceb62d.png

join比concat更可配置:特别是,它有五种连接模式,而concat只有两种。详情请参阅下面的“1:1关系连接”部分。

基于多指数的数据叠加

如果行标签和列标签一致,concat可以执行与垂直堆叠类似的多索引(就像NumPy中的dstack):

c615a26e7788f9b6e0f75ada66773aef.png

如果行和/或列部分重叠,Pandas将相应地对齐名称,这很可能不是你想要的。下面的图表可以帮助你将这个过程可视化:

10964c8b187644dd0eb3aca8575e7772.png

一般来说,如果标签重叠,这意味着dataframe在某种程度上彼此相关,实体之间的关系最好使用关系数据库的术语来描述。

1:1 连接的关系

ebe33bd45b2ec85c2983c71652b56de3.png

当同一组对象的信息存储在几个不同的DataFrame中时,你希望将它们合并为一个DataFrame。

如果要合并的列不在索引中,则使用merge。

154617999f7ee1093cfba1d7974b2d41.png

它所做的第一件事是丢弃索引中的任何内容。然后执行联结操作。最后,将结果从0重新编号为n-1。

如果列已经在索引中,则可以使用join(这只是merge的别名,将left_index或right_index设置为True,并设置不同的默认值)。

05c07556ecbbe1e3e7b241ce95d4845f.png

从这个简化的例子中可以看出(参见上面的全外连接),与关系型数据库相比,Pandas对行顺序的处理相当轻松。左外联结和右外联结比内外联结更容易预测(至少在需要合并的列中有重复值之前是这样)。因此,如果你想保证行顺序,就必须显式地对结果进行排序。

1:n 连接的关系

0b7d6fb72da7040460f0c89a017263a1.png

这是数据库设计中使用最广泛的关系,表A中的一行(例如“State”)可以与表B中的几行(例如城市)相关联,但表B中的每一行只能与表A中的一行相关联(即一个城市只能处于一种状态,但一个状态由多个城市组成)。

就像1:1关系一样,在Pandas中连接一对1:n相关的表,你有两种选择。如果要合并的列或者不在索引中,并且可以丢弃碰巧在两张表的索引中都存在的列,则使用merge。下面的例子会有所帮助:

5b1b7d7192b5e9c212f8e53a1f52744f.png

正如我们已经看到的,merge对行顺序的处理没有Postgres严格:所有声明的语句,保留的键顺序只适用于left_index=True和/或right_index=True(这就是join的别名),并且只在要合并的列中没有重复值的情况下。这就是为什么join有一个sort参数。

现在,如果要合并的列已经在右侧DataFrame的索引中,可以使用join(或者merge with right_index=True,这是完全相同的事情):

701bbdfa7a83e98919991b4e7fa08674.png

这次Pandas保留了左DataFrame的索引值和行顺序。

注意:注意,如果第二个表有重复的索引值,你最终将在结果中得到重复的索引值,即使左表索引是唯一的!

有时,合并的dataframe具有同名的列。merge和join都有解决二义性的方法,但语法略有不同(默认情况下merge会用` _x `, ` _y `来解决,而join会抛出异常),如下图所示:

270e0e4976bb182fcaf1a508339877bd.png

总结:

  • 合并非索引列上的连接,连接要求列被索引

  • merge丢弃左DataFrame的索引,join保留它

  • 默认情况下,merge执行内联结,join执行左外联结

  • 合并不保持行顺序

  • Join可以保留它们(有一些限制)

  • join是合并的别名,left_index=True和/或right_index=True

多个连接

如上所述,当对两个dataframe(如df.join(df1))运行join时,它充当了合并的别名。但是join也有一个` multiple join `模式,它只是concat(axis=1)的别名。

a580af61b5c8fc42fa4f2f1006c50705.png

与普通模式相比,该模式有一些限制:

  • 它没有提供解析重复列的方法

  • 它只适用于1:1关系(索引到索引连接)。

因此,多个1:n关系应该一个接一个地连接。仓库` panda -illustrated `也提供了一个辅助方法,如下所示:

446bd776245292f510f020f623caa2e1.png

pdi.join是Join的一个简单包装器,它接受on、how和后缀参数,以便您可以在一个命令中进行多个联结。与原始的关联操作一样,关联的是属于第一个DataFrame的列,其他DataFrame根据它们的索引进行关联操作。

插入和删除

由于DataFrame是列的集合,因此将这些操作应用到行上比应用到列上更容易。例如,插入一列总是在原地完成,而插入一行总是会生成一个新的DataFrame,如下所示:

cad643f83f5a9816e496fe87e06a0eb8.png

删除列通常不用担心,除了del df['D']和del df。D则没有(Python级别的限制)。

31f5d0b11ac0463ddc8789b0c8c22aee.png

使用drop删除行非常慢,如果原始标签不是唯一的,可能会导致复杂的bug。下图将帮助解释这个概念:

b265a911333533a3ec958ea218585bbc.png

一种解决方案是使用ignore_index=True,它告诉concat在连接后重置行名称:

92d241f451a6ae4db7bab53886ff832d.png

在这种情况下,将name列设置为索引将有所帮助。但对于更复杂的滤波器,它不会。

另一种快速、通用、甚至可以处理重复行名的解决方案是索引而不是删除。为了避免显式地否定条件,我写了一个(只有一行代码的)自动化程序。

e99d3d0a9657f7ce86d710bc13f184cb.png

分组

这个操作已经在Series部分详细描述过了。但是DataFrame的groupby在此基础上有一些特定的技巧。

首先,你可以使用一个名称来指定要分组的列,如下图所示:

845404cd5a2867b8c32f6001e5b9646d.png

如果没有as_index=False, Pandas将进行分组的列指定为索引。如果这不是我们想要的,可以使用reset_index()或指定as_index=False。

通常,数据框中的列比你想在结果中看到的多。默认情况下,Pandas会对所有远端可求和的东西进行求和,因此你需要缩小选择范围,如下所示:

35a2be9782f377107548fa6831bda5bd.png

注意,当对单个列求和时,你将得到一个Series而不是DataFrame。如果出于某种原因,你想要一个DataFrame,你可以:

  • 使用双括号:df.groupby('product')[['quantity']].sum()

  • 显式转换:df.groupby('product')['quantity'].sum().to_frame()

切换到数值索引也会创建一个DataFrame:

  • df.groupby('product', as_index=False)['quantity'].sum()

  • df.groupby('product')['quantity'].sum().reset_index()

但是,尽管外观不寻常,Series的行为就像DataFrames一样,所以可能对pdi.patch_series_repr()进行“整容”就足够了。

显然,不同的列在分组时表现不同。例如,对数量求和完全没问题,但对价格求和就没有意义了。使用。agg可以为不同的列指定不同的聚合函数,如下图所示:

16540c660b65ebb36413eeb80f032027.png

或者,你可以为一列创建多个聚合函数:

2e3b3590d4e180c5789551f6ba0742e4.png

或者,为了避免繁琐的列重命名,你可以这样做:

58f0e94d142984593a78bcb4a7cce030.png

有时,预定义的函数不足以产生所需的结果。例如,在平均价格时使用权重会更好。你可以为此提供一个自定义函数。与Series不同的是,该函数可以访问组中的多个列(它以子dataframe作为参数),如下所示:

ab2ef3da0f4eb920a83728e3e8d3c275.png

不幸的是,你不能把预定义的聚合和几个列级的自定义函数结合在一起,比如上面的那个,因为agg只接受单列级的用户函数。单列范围的用户函数唯一可以访问的是索引,这在某些情况下很方便。例如,那天香蕉以5折的价格出售,如下图所示:

97c5da571e9188159deae03328cdc5e2.png

为了从自定义函数中访问group by列的值,它事先已经包含在索引中。

通常,定制最少的函数可以获得最好的性能。为了提高速度:

  • 通过g.apply()实现多列范围的自定义函数

  • 通过g.agg()实现单列范围的自定义函数(支持使用Cython或Numba进行加速)

  • 预定义函数(Pandas或NumPy函数对象,或其字符串名称)。

  • 预定义函数(Pandas或NumPy函数对象,或其字符串名称)。

数据透视表(pivot table)是一种有用的工具,通常与分组一起使用,从不同的角度查看数据。

旋转和`反旋转`

假设你有一个变量a,它依赖于两个参数i和j。有两种等价的方法将它表示为一个表:

86f46bd14c4bf819ced77e90898be34b.png

当数据是“密集的”(当有很少的0元素)时,` short `格式更合适,而当数据是“稀疏的”(大多数元素为0,可以从表中省略)时,` long `格式更好。当有两个以上的参数时,情况会变得更加复杂。

当然,应该有一种简单的方法来转换这些格式。Pandas为此提供了一个简单方便的解决方案:数据透视表。

作为一个不那么抽象的例子,考虑下表中的销售数据。有两个客户购买了两种产品的指定数量最初,这个数据是短格式的。`要将其转换为`长格式`,请使用df.pivot:

600e3a433c0107f689b586b5b5e0b3c5.png

该命令丢弃了与操作无关的任何信息(索引、价格),并将来自三个请求列的信息转换为长格式,将客户名称放入结果的索引中,将产品名称放入列中,将销售数量放入DataFrame的` body `中。

至于相反的操作,你可以使用stack。它将索引和列合并到MultiIndex中:

f551ecd02759178bacb271633a3b5365.png

另一种选择是使用melt:

5f99e138ed4c8f0f7d63cc21ddd17542.png

注意,melt以不同的方式对结果行进行排序。

Pivot丢失了结果的` body `的名称信息,因此无论是stack还是melt,我们都必须提醒pandas ` quantity `列的名称。

在上面的例子中,所有的值都存在,但这不是必须的:

a2b66e09b696ef4d4d014b1e38ba6118.png

分组值然后旋转结果的做法是如此常见,以至于groupby和pivot被捆绑在一个专用的函数(以及相应的DataFrame方法)数据透视表中:

  • 如果没有columns参数,它的行为与groupby类似

  • 当没有重复的行进行分组时,它的工作原理与pivot类似

  • 否则,它会进行分组和旋转

5ef7f257e60be2a64d412dd04bb9e2d0.png

aggfunc参数控制哪一个聚合函数应该用于分组行(默认为均值)。

为了方便,pivot_table可以计算小计和合计:

be9521d0afbcdfeb6970d52869f21e85.png

一旦创建,pivot表就变成了一个普通的DataFrame,因此可以使用前面描述的标准方法查询它。

cd7e3067d4c7685d9cc788e104a2f493.png

当使用多索引时,透视表特别方便。我们已经见过很多Pandas函数返回多索引DataFrame的例子。让我们仔细看看。

第四部分. MultiIndex

654ad335636b90a218be5e9c1f15287b.png

对于从未听说过Pandas的人来说,多索引(MultiIndex)最直接的用法是使用第二个索引列作为第一个索引列的补充,以唯一地标识每行。例如,为了消除来自不同州的城市的歧义,州的名字通常附加在城市的名字后面。例如,在美国大约有40个springfield(在关系型数据库中,它被称为复合主键)。

你可以在从CSV解析DataFrame后指定要包含在索引中的列,也可以立即作为read_csv的参数。

8d978eb67b506c60d7a95bee9e695adf.png

您还可以使用append=True将现有级别添加到多重索引,如下图所示:

2e86736588c762707640d6ac97bb19fd.png

另一个更典型的用例是表示多维。当你有一组具有特定属性的对象或者随着时间的推移而演变的对象时。例如:

  • 社会学调查的结果

  • ` Titanic `数据集

  • 历史天气观测

  • 锦标赛排名的年表。

这也被称为“面板数据”,Pandas就是以此命名的。

让我们添加这样一个维度:

a05eeb816b3b415b00757076d70ddfbc.png

现在我们有了一个四维空间,如下所示:

  • 年形成一个(几乎连续的)维度

  • 城市名称沿第二条排列

  • 第三个州的名字

  • 特定的城市属性(“人口”、“密度”、“面积”等)在第四个维度上起到了“刻度线”的作用。

下图说明了这个概念:

eb3eabfe79db0ef9eca0fcff075cc951.png

为了给对应列的尺寸名称留出空间,Pandas将整个标题向上移动:

e7557357d0eee349e0f0a7bf3fb48019.png

分组

关于多重索引需要注意的第一件事是,它并不按照它可能出现的情况对任何内容进行分组。在内部,它只是一个扁平的标签序列,如下所示:

f8367ede8d19acf7e1965b74f3381bf6.png

你可以通过对行标签进行排序来获得相同的groupby效果:

e21c45bc10c637d737b9ef3004d07529.png

你甚至可以通过设置相应的Pandas选项来完全禁用视觉分组
:pd.options.display.multi_sparse=False。

类型转换

Pandas(以及Python本身)区分数字和字符串,因此在无法自动检测数据类型时,通常最好将数字转换为字符串:

pdi.set_level(df.columns, 0, pdi.get_level(df.columns, 0).astype('int'))

如果你喜欢冒险,可以使用标准工具做同样的事情:

df.columns = df.columns.set_levels(df.columns.levels[0].astype(int), level=0)

但为了正确使用它们,你需要理解什么是` levels `和` codes `,而pdi允许你使用多索引,就像使用普通的列表或NumPy数组一样。

如果你真的想知道,` levels `和` codes `是特定级别的常规标签列表被分解成的东西,以加速像pivot、join等操作:

  • pdi.get_level(df, 0) == Int64Index([2010, 2010, 2020, 2020])

  • df.columns.levels[0] == Int64Index([2010, 2020])

  • df.columns.codes[0] == Int64Index([0, 1, 0, 1])

使用多重索引构建一个Dataframe

除了从CSV文件读取和从现有列构建外,还有一些方法可以创建多重索引。它们不太常用——主要用于测试和调试。

由于历史原因,使用Panda自己的多索引表示的最直观的方法不起作用。

9b0f8183d5c127aee9552a07805e5233.png

这里的` Levels `和` codes `(现在)被认为是不应该暴露给最终用户的实现细节,但我们已经拥有了我们所拥有的。

可能最简单的构建多重索引的方法如下:

ffa0f5cb133d8cc10aabab09a6699692.png

这样做的缺点是必须在单独的一行中指定级别的名称。有几种可选的构造函数将名称和标签捆绑在一起。

29865851361682abb1d3c88aaf273cc0.png

当关卡形成规则结构时,您可以指定关键元素,并让Pandas自动交织它们,如下所示:

292fefb50adf434e8f2669f043b9a29f.png

上面列出的所有方法也适用于列。例如:

0d838f66f85268c54c02babf4eb3f7e8.png

使用多重索引进行索引

通过多重索引访问DataFrame的好处是,您可以轻松地使用熟悉的语法一次引用所有级别(可能省略内部级别)。

列——通过普通的方括号

09ad1d5a38ac4179ebf5f0f22aacc0ea.png

行和单元格——使用.loc[]

648af2ff014c2c22b4f392caa713afab.png

现在,如果你想选择俄勒冈州的所有城市,或者只留下包含人口的列,该怎么办?Python语法在这里有两个限制。

1. 没有办法区分df['a', 'b']和df[('a', 'b')]——它是以同样的方式处理的,所以你不能只写df[:, ' Oregon ']。否则,Pandas将永远不知道你指的是列Oregon还是第二级行Oregon

2. Python只允许在方括号内使用冒号,而不允许在圆括号内使用冒号,所以你不能写df.loc[(:, 'Oregon'),:]

在技术方面,这并不难安排。我给DataFrame打了猴补丁,添加了这样的功能,你可以在这里看到:

f61ce42f6b39b60dddddf6d0d3754d67.png

这种语法唯一的缺点是,当你使用两个索引器时,它返回一个副本,所以你不能写df.mi[:, ' Oregon ']。Co [' population '] = 10。有许多可选的索引器,其中一些允许这样的赋值,但它们都有自己的特点:

1. 您可以将内层与外层交换,并使用括号。

3a90695fea34e270f12a8c3bc748c1dc.png

因此,df[:, 'population']可以用df.swaplevel(axis=1)['population']实现。

这感觉很hacky,不方便超过两层。

2. 你可以使用xs方法:df.xs (' population ', level=1, axis=1)。

它给人的感觉不够python化,尤其是在选择多个关卡时。这种方法无法同时过滤行和列,因此名称xs(代表“横截面”)背后的原因并不完全清楚。它不能用于设置值。

3.可以为pd创建别名。idx=pd.IndexSlice;df.loc [:, idx[:, ' population ']]

这更符合python风格,但要访问元素,必须使用别名,这有点麻烦(没有别名的代码太长了)。您可以同时选择行和列。可写的。

4. 你可以学习如何使用slice代替冒号。如果你知道a[3:10:2] == a[slice(3,10,2)],那么你可能也会理解下面的代码:df.loc[:, (slice(None), ' population ')],但它几乎无法读懂。您可以同时选择行和列。可写的。

作为底线,Pandas有多种使用括号使用多重索引访问DataFrame元素的方法,但没有一种方法足够方便,因此他们不得不采用另一种索引语法:

5. 一个用于.query方法的迷你语言:df.query(' state=="Oregon" or city=="Portland" ')。

它方便快捷,但缺乏IDE的支持(没有自动补全,没有语法高亮等),而且它只过滤行,而不是列。这意味着你不能在不转置DataFrame的情况下用它实现df[:, ' population '](除非所有列的类型都相同,否则会丢失类型)。Non-writable。

叠加与拆分

Pandas没有针对列的set_index。向列中添加层次的一种常见方法是将现有的层次从索引中“解栈”:

3b72ac2513b8f3a992a2698d143d98a1.png

Pandas的栈与NumPy的栈有很大不同。让我们看看文档中对命名约定的说明:

“该函数的命名类似于重新组织的书籍集合,从水平位置并排(dataframe的列)到垂直堆叠(在dataframe的索引中)。”

“在上面”的部分听起来并不能让我信服,但至少这个解释有助于记住谁把东西朝哪个方向移动。顺便说一下,Series有unstack,但没有stack,因为它已经“堆叠”了。由于是一维的,Series在不同情况下可以作为行向量或列向量,但通常被认为是列向量(例如dataframe列)。

例如:

ed11ce97753272b51d00357303618d51.png

您还可以通过名称或位置索引指定要堆叠/解堆叠的级别。在这个例子中,df.stack()、df.stack(1)和df.stack(' year ')与df1.unstack()、df1.unstack(2)和df1.unstack(' year ')产生相同的结果。目的地总是在“最后一层之后”,并且不可配置。如果需要将级别放在其他地方,可以使用df.swaplevel().sort_index()或pdi。swap_level (df = True)

列必须不包含重复的值才能堆叠(在反堆叠时,索引也是如此):

db33efbdda0b2c57b82b5538083fb5eb.png

如何防止叠加/分解排序

stack和unstack都有一个坏习惯,会不可预测地按字典顺序排序结果索引。这有时可能令人恼火,但这是在有大量缺失值时给出可预测结果的唯一方法。

考虑下面的例子。你希望一周中的天数以何种顺序出现在右边的表中?

249912606a6c174f99004a8b617f8064.png

你可以推测,如果John的星期一在John的星期五的左边,那么就是' Mon ' < ' Fri ',类似地,Silvia的' Fri ' < ' Sun ',因此结果应该是' Mon ' < ' Fri ' < ' Sun '。这是合法的,但是如果剩余的列顺序不同,比如' Mon ' < ' frii '和' Tue ' < ' frii ',该怎么办?或者' Mon ' < ' friday '和' Wed ' < ' Sat ' ?

好吧,一周没有那么多天,Pandas可以根据先验知识推断出顺序。但是,人类还没有得出一个决定性的结论,那就是星期天应该作为一周的结束还是开始。Pandas应该默认使用哪种顺序?阅读区域设置?那么不那么琐碎的顺序呢,比如美国的州的顺序?

在这种情况下,Pandas所做的只是简单地按字母顺序排序,如下所示:

fb3efd88a292a11e1448c43a4c1e2ec2.png

虽然这是一个合理的默认,但感觉上仍然是错误的。应该有一个解决方案!有一个。它被称为CategoricalIndex。即使缺少一些标签,它也会记住顺序。它最近已经顺利集成到Pandas工具链中。它唯一缺少的是基础设施。它很难建立;它是脆弱的(在某些操作中会退回到对象),但它是完全可用的,并且pdi库有一些帮助程序可以陡峭地提高学习曲线。

例如,要告诉Pandas锁定存储产品的简单索引的顺序(如果你决定将一周中的天数解栈回列,则不可避免地会排序),你需要编写像df这样可怕的代码。index = pd.CategoricalIndex(df. index)df指数。指数排序= True)。它更适合多索引。

pdi库有一个辅助函数locked(以及一个默认为inplace=True的别名lock),通过将某个多索引级别提升到CategoricalIndex来锁定该级别的顺序:

89e230dc34fb901a50c49b29a759d760.png

等级名称旁边的勾选标记表示等级被锁定。它可以使用pdi.vis(df)手动可视化,也可以使用pdi.vis_patch()对DataFrame HTML输出进行monkey补丁自动可视化。应用补丁后,在Jupyter单元中简单地写` df `将显示锁定顺序的所有级别的复选标记。

Lock和locked在简单的情况下自动工作(如客户端名称),但在更复杂的情况下(如缺少日期的星期几)需要用户提示。

df503400730b17ad48b6aa9d3914aa9e.png

在级别切换到CategoricalIndex之后,它会在sort_index、stack、unstack、pivot、pivot_table等操作中保持原来的顺序。

不过,它很脆弱。即使像df[' new_col '] = 1这样简单的操作也会破坏它。使用pdi.insert (df。columns, 0, ' new_col ', 1)用CategoricalIndex正确处理级别。

操作级别

除了前面提到的方法之外,还有一些其他的方法:

  • pdi.get_level(obj, level_id)返回通过数字或名称引用的特定级别,可用于DataFrames, Series和MultiIndex

  • pdi.set_level(obj, level_id, labels)用给定的数组(list, NumPy array, Series, Index等)替换关卡的标签

0b0eac56ef882a2d0f6505064697edfa.png

  • pdi.insert_level (obj, pos, labels, name)使用给定的值添加一个层级(必要时适当广播)

  • pdi.drop_level(obj, level_id)从多重索引中删除指定的级别

4b8eabbe8d83375f1fd77e276441794d.png

pdi.swap_levels (obj, src=-2, dst=-1)交换两个级别(默认是两个最内层的级别)

pdi.move_level (obj, src, dst)将特定级别src移动到指定位置dst

fcb6697ace0200a551d940777dd122a5.png

除了上述参数外,本节中的所有函数还有以下参数:

  • axis=None其中None对于DataFrame表示“列”,对于Series表示“索引”

  • sort=False,可选在操作之后对相应的多索引进行排序

  • inplace=False,可选地原地执行操作(不能用于单个索引,因为它是不可变的)。

上面的所有操作都是从传统意义上理解“级别”这个词的(级别的标签数量与数据框中的列数量相同),隐藏了索引的机制。标签和索引。来自最终用户的代码。

在极少数情况下,当移动和交换单独的关卡不够时,您可以使用纯Pandas调用:df一次性重新排序所有关卡。columns = df.columns.reorder_levels([' M ', ' L ', ' K '])其中[' M ', ' L ', ' K ']是层的期望顺序。

通常,使用get_level和set_level对标签进行必要的修复就足够了,但如果你想一次对多索引的所有级别应用转换,Pandas有一个(命名不明确)函数rename接受一个dict或一个函数:

7a59e9fe954af319b19be22b84c713e8.png

至于重命名级别,它们的名称存储在.names字段中。该字段不支持直接赋值(为什么不?):df.index.names[1] = ' x ' # TypeError,但可以作为一个整体替换:

102d10b1f9200ba207515ebcedd46052.png

当你只需要重命名一个特定的级别时,语法如下:

06674c94307197a8365e5db66d36334e.png

将多索引转换为平面索引并恢复它

正如我们在上面看到的,便捷的查询方法只解决了处理行中的多索引的复杂性。尽管有这么多的辅助函数,但当某些Pandas函数返回列中的多索引时,对初学者来说会有一个震惊的效果。因此,pdi库具有以下内容:

  • join_levels(obj, sep=’_’, name=None) 将所有多索引级别连接到一个索引

  • split_level(obj, sep=’_’, names=None)将索引拆分回多索引

1fb1d6081b5345701ec16ea2ec47c760.png

它们都有可选的axis和inplace参数。

排序MultiIndex

由于多索引由多个级别组成,因此排序比单索引更做作。这仍然可以使用sort_index方法完成,但可以使用以下参数进行进一步微调。

5ccbbb17918e9c03c9ea615afae62110.png

要对列级别进行排序,指定axis=1。

读写多索引dataframe到磁盘

Pandas可以以完全自动化的方式将具有多重索引的DataFrame写入CSV文件:df.to_csv('df.csv ')。但是在读取这样的文件时,Pandas无法自动解析多重索引,需要用户的一些提示。例如,要读取具有三层高列和四层宽索引的DataFrame,你需要指定pd.read_csv('df.csv', header=[0,1,2], index_col=[0,1,2,3])。

这意味着前三行包含有关列的信息,后续每一行的前四个字段包含索引级别(如果列的级别不止一个,你不能再通过名称来引用行级别,只能通过编号)。

手动解读多索引中的层数是不方便的,所以更好的主意是在将DataFrame保存到CSV之前,stack()所有列头层,并在读取后将它们解stack()。

如果你需要“置之不理”的解决方案,可能需要研究二进制格式,例如Python的pickle格式:

直接调用:df.to_pickle('df.pkl'), pd.read_pickle('df.pkl')

使用storemagic在Jupyter %store df然后%store -r df(存储在$
HOME/.ipython/profile_default/db/autorestore)

Python的pickle小巧而快速,但只能在Python中访问。如果您需要与其他生态系统互操作,请查看更标准的格式,如Excel格式(在读取MultiIndex时需要与read_csv相同的提示)。代码如下:

!pip install openpyxl
df.to_excel('df3.xlsx')
df.to_pd.read_excel('df3.xlsx', header=[0,1,2], index_col=[0,1,2,3])

或者查看其他选项(参见文档)。

MultiIndex算术

当使用多索引数据框时,与普通数据框适用相同的规则(见上文)。但是处理细胞的一个子集有它自己的一些特性。

用户可以通过外部的多索引级别更新部分列,如下所示:

fe33acee1bcf7fbad0af049ecc862e3e.png

如果想保持原始数据不变,可以使用df1 = df.assign(population=df.population*10)。

你也可以用density=df.population/df.area轻松获得人口密度。

7581a0e2433994c959be06386d6c231e.png

但不幸的是,你不能用df.assign将结果赋值给原始的dataframe。

一种方法是将列索引的所有不相关级别堆叠到行索引中,执行必要的计算,然后将它们解堆叠回去(使用pdi)。锁以保持列的原始顺序)。

fc95ca3fba1f9569252f81b329d8a452.png

或者,你也可以使用pdi.assign:

ff111772b8aa94bfa5dbd6bc1fb54366.png

pdi.assign是锁定顺序感知的,所以如果你给它一个(多个)锁定级别的dataframe,它不会解锁它们或后续的栈/解栈/等。操作将保持原始的列和行顺序。

总而言之,Pandas是分析和处理数据的好工具。希望这篇文章能帮助你理解“如何”和“为什么”解决典型问题,并欣赏Pandas库的真正价值和美丽。

d0b809e019538a962ef28e389d15aec7.jpeg

最后推荐一下我们团队写的量化小册的内容,45篇内容!从Python安装,入门,数据分析,爬取股票基金的历史+实时数据,以及如何写一个简单量化策略,策略回测,如何看资金曲线统统都有介绍!非常超值!

欢迎订阅:原价299 早鸟价2杯咖啡钱,即可永久阅读。满400人又要涨价了,现在的价格非常非常低,只要2杯奶茶,就可以终身订阅+课程源码,还有永久陪伴群。48小时无理由退款,放心食用!

afa0e1a146e0978b15245201db8fe8f7.png

往期推荐
量化: 如何用Python爬取创业板历史+实时股票数据!|实战股票分析篇利用Pandas 9招挖掘五粮液股价!|实战股票数据分析篇 Pandas滚动操作 |量化股票第一步,用Python画股票K线,双均线图,可视化你的股票数据!|如何用Python爬取全部800多只ETF基金数据!|如何用Python写一个双均线策略 |如何用Python开发一个多策略机器人!上篇!|Python量化系列-用布林策略买五粮液能赚多少钱?|只要4秒钟!用Python 获取上证指数34年的历史日线数据!

 
入门: 最全的零基础学Python的问题  | 零基础学了8个月的Python  | 实战项目 |学Python就是这条捷径

干货:爬取豆瓣短评,电影《后来的我们》 | 38年NBA最佳球员分析 |   从万众期待到口碑扑街!唐探3令人失望  | 笑看新倚天屠龙记 | 灯谜答题王 |用Python做个海量小姐姐素描图 |碟中谍这么火,我用机器学习做个迷你推荐系统电影

趣味:弹球游戏  | 九宫格  | 漂亮的花 | 两百行Python《天天酷跑》游戏!

AI: 会做诗的机器人 | 给图片上色 | 预测收入 | 碟中谍这么火,我用机器学习做个迷你推荐系统电影

小工具: Pdf转Word,轻松搞定表格和水印! | 一键把html网页保存为pdf!|  再见PDF提取收费! | 用90行代码打造最强PDF转换器,word、PPT、excel、markdown、html一键转换 | 制作一款钉钉低价机票提示器! |60行代码做了一个语音壁纸切换器天天看小姐姐!

技术人如何用工程化思维打造高传播技术内容:从选题到分发的完整策略 在技术传播领域,内容创作常面临专业深度与受众广度之间的矛盾。其核心原理在于通过结构化思维和数据分析,将复杂概念转化为易于理解的信息。从技术价值看,这不仅提升了个人品牌影响力,也通过输出倒逼输入巩固了技术理解。在应用场景上,无论是博客、GitHub README还是技术社区分享,都需要一套系统化方法。本文聚焦于如何运用工程化思维,像开发项目一样设计、测试和迭代内容,通过流量漏斗与需求金字塔模型精准选题,并借助类比和图示等技巧降低理解门槛,最终实现技术内容的高效生产与广泛传播。 阅读详情

相关推荐

pandas教程

pandas教程,详细的介绍的pandas的使用办法,以及调用api函数

pandas的菜鸟级应用(谁都能学会)

简述: 这是本人第一篇博文,因为自己想向最近很火的人工智能,大数据,进行靠拢。所以就从基本做起,掌握基本的python 的库,像 pandas ,numpy 。水平有限大家见谅。 pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。(来自百度百科)

lemon_kui的博客 6860

基于ensp大学网络规划与设计(完整文档+ensp拓扑图)

大家好,我是小华学长,一名计算机领域的博主。经过多年的学习和实践,我积累了丰富的计算机知识和经验,在这里我想与大家分享我的学习心得和技巧,帮助你成为更好的程序员。 作为一名计算机博主,我一直专注于编程、算法、软件开发等领域,在这些方面积累了大量的经验。我相信分享是一种双赢的方式,通过分享,我可以帮助他人提升技术水平,同时也能够得到学习交流的机会。 在我的文章中,你将会看到我对于各种编程语言、开发工具以及常见问题的解析和分析。我会结合自己的实际项目经验,为你提供实用的解决方案和优化技巧。我相信这些经验不仅能够

qq1325513482的博客 5万+

推荐收藏!3.5万字图解 Pandas!

↓推荐关注↓大家好,在 Python 各个工具包中,最频繁使用的应该就是 Pandas 了。今天我以图解的方式给大家介绍 Pandas 中各种常用的操作,内容有点长,喜欢记得点赞、收藏、关注。第一部分:Pandas 展示请看下表:它描述了一个在线商店的不同产品线,共有四种不同的产品。与前面的例子不同,它可以用NumPy数组或Pandas DataFrame表示。但让我们看一下它的一些常见操作。1....

cainiao_python的博客 424

海思方案定制hi3531dv200/SS528 DVR方案解析:从硬件选型到编解码实战应用

海思方案,Hi3518EV100,Hi3518CV100,Hi3515CV100,Hi3516CV100,Hi3516ECV100,Hi3516D,Hi3516A,Hi3519,Hi3520D,Hi3521A,Hi3535,Hi3531,Hi3536,Hi3536C,Hi3536D,Hi3518EV200,Hi3518EV201,Hi3520DV200,Hi3516CV200,Hi3516CV300,Hi3516AV200,Hi3520DV300,Hi3519V101,sd3403,hi3519av200

1586

codesys工程ST语言学习笔记(二)写文件操作与添加库方法

ST语言文件读写功能 由于实验中需要大量的数据,文件读写比较方便,但是网上的文件读写的程序很多都用不了,小编将自己的工程发布出来

sf9090的博客 1万+

pandas菜鸟速学-series

一个基于numpy的数据处理数据分析的工具。特点:Pandas 的主要数据结构是 Series (一维数据)与 DataFrame(二维数据),这两种数据结构足以处理金融、统计、社会科学、工程等领域里的大多数典型用例。

qiming666的博客 889

并行计算:从概念起源到多层次架构设计及其发展历程的全面解析

20世纪70年代,第一台并行计算机于1972年产生(ILLIAC IV,伊利诺依大学),由64个处理器组成,可扩展性好,但可编程性差。如有21亩地需要除草,一个人一天只能除一亩地的草,那么需要21天才能除完草,这在现实中是不太可能的,因庄稼是有时间段的。其二是机群系统是高性能计算机的一种,它的技术基础和工业基础都是商品化和标准化。之所以称为“专用”,并不是说它们只能运行某种应用,是指它们的组成部件是专门设计的,它们的CPU板、内存板和I/O板,甚至操作系统,都是不能在其它系统中使用的。

1656

Python数据分析基础技术之pandas(史上最全面)

pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。简单地说,你可以把 Pandas 看作是 Python 版的 Excel。 ...

薛定谔的猫-前端领域 7万+

世界模型(World Models)进展全景调研(截至 2025-08)

A5) 2019-07(待核验) | C-SWM:Contrastive Structured World Models(Kipf et al.)A6) 2019-07(待核验) | SLAC:Stochastic Latent Actor-Critic(Lee et al.)A3) 2015-12(背景注记,待核验) | Embed to Control(E2C,Watter et al.)Nature 2020)Repro/Code:werner-duvaud/muzero-general(社区)

u013250861的博客 489

AE(自动曝光)调试策略:曝光曲线设计与过曝控制

自动曝光(AE, Auto Exposure)系统是图像质量控制链路中的核心模块之一,其性能直接决定了成像亮度是否稳定、细节是否完整、场景切换是否自然。在现代移动终端影像系统中,AE 不仅需要适应不同光照强度和复杂环境,还需兼顾人脸优先、HDR触发、视频帧率控制等多目标优化需求。本文基于高通 Snapdragon 和 MTK Dimensity 等主流平台的调试经验,系统梳理了 AE 模型设计原则、曝光曲线配置、测光策略选择与过曝抑制机制,并结合典型实战案例,提供可复制的工程落地路径。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 3097

pandas之Dataframe 菜鸟教程

import numpy as np import pandas as pd print("=============Dataframe:基本概念及创建=====================") ''' Pandas数据结构Dataframe:基本概念及创建 "二维数组"Dataframe:是一个表格型的数据结构,包含一组有序的列,其列的值类型可以是数值、字符串、布尔值等。 Dataframe中的数据以一个或多个二维块存放,不是列表、字典或一维数组结构。 ''' # Dataframe 数据结构 # D

林中有神君 2166

华为OD机试真题 新系统2026-04-01 Python&JS 实现【空间占用计算】

员工A的磁盘空间经常被耗尽,他需要找到占用空间最大的目录或文件,然后决定如何清理文件释放空间。给定某一目录,请编写程序帮助他统计该目录内一级子目录和文件的占用空间,并返回目标目录一级子项(文件或子目录)中占用空间最大的项。

MISAYAONE的博客 1316

硕士毕业,自学Python数据科学!

给大家推荐一位好友:Peter,公众号【尤而小屋】的主理人。尤而小屋三周岁啦!硕士毕业后Peter自学Python转行数据分析,喜欢「Python机器学习、爬虫、数据分析,钟爱可视化」,创作主要有:《Pandas图解入门教程》,《高级可视化神器Plotly入门实战》,《机器学习kaggle案例分析》,《MySQL经典50题》。尤而小屋「Python机器学习、数据分析、可视化」的好地方,这里的原创文...

weixin_43373042的博客 208

基于 STM32 的智慧农业温室控制系统设计与实现

本文提出一种基于 STM32 微控制器的智慧农业温室控制系统设计方案,通过集成多类型环境传感器、执行机构及无线通信模块,实现对温室内温湿度、光照、土壤湿度等参数的实时监测与自动调控。文中详细阐述硬件选型、电路连接及软件实现流程,并附关键代码示例,为智慧农业领域提供低成本、高可靠性的温室控制解决方案。

weixin_42300449的博客 1927

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Python数据分析宝藏地带!

给大家推荐一个Python机器学习、数据分析的好地方:尤而小屋。这里的原创文章高达260+篇,主要内容涉及:Python机器学习、数据分析、爬虫、kaggle案例分享、Pandas、MySQL、可视化、工具利器等,大家一起来看看,可以关注学习起来喔❤️下面是部分优质原创文章:一、机器学习+kaggle案例 机器学习和数据分析案例分享是尤而小屋的核心内容,主要包含机器学习理...

weixin_38753422的博客 161

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

硕士毕业,自学Python入门数据科学!

给大家推荐一位好友:Peter,公众号【尤而小屋】的主理人。硕士毕业后Peter自学Python转行数据分析,喜欢Python机器学习、爬虫、数据分析,钟爱可视化,创作主要有:《Pandas图解入门教程》,《高级可视化神器Plotly入门实战》,《机器学习kaggle案例分析》,《MySQL经典50题》。尤而小屋Python机器学习、数据分析、可视化的好地方,这里的原创文章高达270+篇,大家一起...

baidu_25854831的博客 284

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【深度学习-Day 8】让数据说话:Python 可视化双雄 Matplotlib 与 Seaborn 教程

在深度学习的征途中,我们不仅需要与冰冷的数字和复杂的算法打交道,更需要一种直观的方式来理解数据、洞察模型行为并有效地展示研究成果。“一图胜千言”,数据可视化正是连接数据与洞察的桥梁。它能够帮助我们发现隐藏在数据背后的模式、趋势和异常点,从而更好地指导我们的数据分析和模型调优工作。在 Python 的生态系统中,Matplotlib 和 Seaborn 是两个功能强大且广受欢迎的数据可视化库。Matplotlib 提供了灵活的底层绘图接口,几乎可以绘制任何类型的静态、动态、交互式图表。

吴师兄大模型的博客 1719

强烈推荐一位数据挖掘工程师

今天给大家隆重推荐一位好友:Peter,公众号【尤而小屋】的主理人,一名爱好美食的数据挖掘工程师。985硕士毕业后Peter自学Python转行数据科学,喜欢Python、机器学习、爬虫、数据分析、可视化,创作主要有:《Pandas图解入门教程》,《高级可视化神器Plotly入门实战》,《机器学习kaggle案例分析》,《MySQL经典50题》。关注公众号:尤而小屋,一个温馨且有爱的小屋尤而小屋原...

weixin_38753422的博客 212

数学建模核心方法:从优化、评价到预测与统计的实战指南

数学建模是将现实世界问题转化为数学语言进行分析与求解的系统性方法,其核心在于通过数学工具实现问题的抽象、分析与优化。从原理层面看,它依赖于优化思维在约束中寻找最优解,运用评价与决策思维处理多准则问题,并借助预测与分类思维从数据中识别模式。在技术价值上,数学建模为复杂决策提供了量化基础和科学依据,显著提升了方案的可靠性与效率。其应用场景极为广泛,涵盖生产计划、资源分配、风险评估、市场预测及智能决策等多个工程与商业领域。本文聚焦于数学建模的常用方法,深入剖析了优化思维、层次分析法等核心范式,并结合统计分析与线性

weixin_30838873的博客 376

数学建模实战:基于多维特征融合的文本可读性评估模型

文本可读性评估是自然语言处理与教育技术交叉领域的基础问题,其核心在于将主观的阅读体验转化为客观的量化指标。传统方法如Flesch-Kincaid、Gunning Fog等公式,主要依赖词汇长度、句子长度等表层统计特征进行计算,原理相对直观,但难以捕捉语义深度和概念复杂度。现代数据科学方法通过引入词汇多样性、句法结构、语义抽象度等多维度特征,结合机器学习模型进行融合,显著提升了评估的准确性与解释性。这种技术对于教育内容分级、辅助阅读系统开发、以及信息无障碍设计具有重要价值。本文以数学建模竞赛题为背景,详细阐述

keke1314520的博客 326

数学建模竞赛C题解题心法:从问题抽象到模型求解的完整实战指南

数学建模是将现实世界复杂问题抽象为数学问题,并通过构建模型进行求解与分析的核心方法。其基本原理在于通过定义变量、目标与约束,将定性描述转化为可量化的数学表达式。这一过程的技术价值在于为资源分配、预测决策、系统优化等复杂场景提供了科学、严谨的解决方案。在供应链优化、定价策略、风险评估等应用场景中,数学建模能有效提升决策质量与效率。本文聚焦于数学建模竞赛中的综合性C题,深入剖析了从问题翻译、模型选型到求解与检验的完整流程,并重点探讨了混合整数规划、启发式算法等关键技术在解决复杂优化问题中的应用,为参赛者提供了从

weixin_33896726的博客 397

数学建模核心理论与实战指南:从模型分类到算法应用

数学建模是将现实世界复杂问题抽象为数学结构,并通过计算求解以指导决策的关键技术。其核心原理在于通过合理简化与假设,抓住问题主要矛盾,构建描述变量关系的数学模型。这一过程的技术价值在于为优化资源配置、预测趋势、评估方案等提供了科学量化工具。在应用场景上,数学建模广泛渗透于生产调度、物流规划、金融分析、流行病预测及人工智能等领域。本文聚焦于模型构建的通用流程与关键环节,深入剖析了优化类、评价预测类、机理分析类及统计分析类等主流模型的应用逻辑,并结合线性规划、时间序列分析、微分方程数值求解等具体算法,探讨了从问题

weixin_30243533的博客 397
上一篇: pywinauto,一款Win自动化利器!
下一篇: 6月,一个新方向爆了,100k很稳...
菜鸟学Python
博客等级 码龄9年 8087粉丝 571原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值