当前位置: 首页 > news >正文

网站正在升级建设中代码怎样做视频网站的外链

网站正在升级建设中代码,怎样做视频网站的外链,wordpress 升级后 插件,数据库和网站Pandas 展示 请看下表: 它描述了一个在线商店的不同产品线#xff0c;共有四种不同的产品。与前面的例子不同#xff0c;它可以用NumPy数组或Pandas DataFrame表示。但让我们看一下它的一些常见操作。 1. 排序 使用Pandas按列排序更具可读性#xff0c;如下所示: 这里arg…Pandas 展示 请看下表: 它描述了一个在线商店的不同产品线共有四种不同的产品。与前面的例子不同它可以用NumPy数组或Pandas DataFrame表示。但让我们看一下它的一些常见操作。 1. 排序 使用Pandas按列排序更具可读性如下所示: 这里argsort(a[:1])计算使a的第二列按升序排序的排列然后a[…]相应地对a的行重新排序。Pandas可以一步完成。 2.按多列排序 如果我们需要使用weight列来对价格列进行排序情况会变得更糟。这里有几个例子来说明我们的观点: 在NumPy中我们先按重量排序然后再按价格排序。稳定排序算法保证第一次排序的结果不会在第二次排序期间丢失。NumPy还有其他实现方法但没有一种方法像Pandas那样简单优雅。 3. 添加一列 使用Pandas添加列在语法和架构上要好得多。下面的例子展示了如何操作: Pandas不需要像NumPy那样为整个数组重新分配内存;它只是添加了对新列的引用并更新了列名的 registry 。 4. 快速元素搜索 在NumPy数组中即使你查找的是第一个元素你仍然需要与数组大小成正比的时间来查找它。使用Pandas你可以索引你期望被查询最多的列并将搜索时间减少到一个常量。 index列有以下限制。 它需要内存和时间来构建。 它是只读的(需要在每次追加或删除操作后重新构建)。 这些值不需要是唯一的但是只有当元素是唯一的时候加速才会发生。 它需要预热:第一次查询比NumPy稍慢但后续查询明显快得多。 5. 按列连接join 如果你想从另一张表中获取基于同一列的信息NumPy几乎没有任何帮助。Pandas更好特别是对于1:n的关系。 Pandas join具有所有熟悉的“内”、“左”、“右”和“全外部”连接模式。 按列分组 数据分析中的另一个常见操作是按列分组。例如要获得每种产品的总销量你可以这样做: 除了sum之外Pandas还支持各种聚合函数:mean、max、min、count等。 7. 数据透视表 Pandas最强大的功能之一是“枢轴”表。这有点像将多维空间投影到二维平面上。 虽然用NumPy当然可以实现它但这个功能没有开箱即用尽管它存在于所有主要的关系数据库和电子表格应用程序(ExcelWPS)中。 Pandas用df.pivot_table将分组和旋转结合在一个工具中。 简而言之NumPy和Pandas的两个主要区别如下: 现在让我们看看这些功能是否以性能损失为代价。 Pandas速度 我在Pandas的典型工作负载上对NumPy和Pandas进行了基准测试:5-100列10³- 10⁸行整数和浮点数。下面是1行和1亿行的结果: 看起来在每一次操作中Pandas都比NumPy慢! 当列数增加时情况不会改变(可以预见)。至于行数依赖关系(在对数尺度下)如下所示: 对于小数组(少于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级别上强制执行)nananything会得到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等等。突然间…… 对于超过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 Series是NumPy中的一维数组是表示其列的DataFrame的基本组成部分。尽管与DataFrame相比它的实际重要性正在降低(你可以在不知道Series是什么的情况下完美地解决许多实际问题)但如果不首先学习Series和Index你可能很难理解DataFrame是如何工作的。 在内部Series将值存储在普通的NumPy vector中。因此它继承了它的优点(紧凑的内存布局、快速的随机访问)和缺点(类型同质、缓慢的删除和插入)。最重要的是Series允许使用类似于字典的结构index通过label访问它的值。标签可以是任何类型(通常是字符串和时间戳)。它们不必是唯一的但唯一性是提高查找速度所必需的许多操作都假定唯一性。 如你所见现在每个元素都可以通过两种替代方式寻址:通过 label (使用索引)和通过 position (不使用索引): 按“位置”寻址有时被称为“位置索引”这只是增加了混淆。 一对方括号是不够的。特别是: S[2:3]不是解决元素2最方便的方式 如果名称恰好是整数s[1:3]就会产生歧义。它可能意味着名称1到3包含或位置索引1到3不包含。 为了解决这些问题Pandas还有两种“风格”的方括号你可以在下面看到: .loc总是使用标号并且包含间隔的两端。 .iloc总是使用“位置索引”并排除右端。 使用方括号而不是圆括号的目的是为了访问Python的切片约定:你可以使用单个或双冒号其含义是熟悉的start:stop:step。像往常一样缺少开始(结束)意味着从序列的开始(到结束)。step参数允许使用s.iloc[::2]引用偶数行并使用s[Paris:Oslo:-1]以相反的顺序获取元素。 它们还支持布尔索引(使用布尔数组进行索引)如下图所示: 你可以在下图中看到它们如何支持 fancy indexing (用整数数组进行索引): Series最糟糕的地方在于它的视觉表现:出于某种原因它没有一个很好的富文本外观所以与DataFrame相比它感觉像是二等公民: 我对这个Series做了补丁让它看起来更好如下所示: 垂直线表示这是一个Series而不是一个DataFrame。Footer在这里被禁用了但它可以用于显示dtype特别是分类类型。 您还可以使用pdi.sidebyside(obj1, obj2…)并排显示多个Series或dataframe: 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(start0, stop1000000, step1)s.index.memory_usage() # in bytes 128 # the same as for Series([0.]) 现在如果我们删除一个元素索引隐式地转换为类似于dict的结构如下所示: s.drop(1, inplaceTrue)s.index Int64Index([ 0, 2, 3, 4, 5, 6, 7,...999993, 999994, 999995, 999996, 999997, 999998, 999999],dtypeint64, length999999)s.index.memory_usage() 7999992 该结构消耗8Mb内存!为了摆脱它回到轻量级的类range结构添加如下代码: s.reset_index(dropTrue, inplaceTrue)s.index RangeIndex(start0, stop999999, step1)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 } inplaceTrue) Index有一个名称(在MultiIndex的情况下每个级别都有一个名称)。不幸的是这个名称在Pandas中没有得到充分使用。一旦你在索引中包含了这一列就不能再使用df了。不再使用列名表示法并且必须恢复为可读性较差的df。指数还是更通用的df。loc对于多索引情况更糟。一个明显的例外是df。Merge -你可以通过名称指定要合并的列无论它是否在索引中。 同样的索引机制用于标记dataframe的行和列以及序列。 按值查找元素 Series内部由一个NumPy数组和一个类似数组的结构index组成如下所示: Index提供了一种通过标签查找值的方便方法。那么如何通过值查找标签呢? s.index[s.tolist().find(x)] # faster for len(s) 1000 s.index[np.where(s.valuesx)[0][0]] # faster for len(s) 1000 我编写了find()和findall()两个简单的封装器它们运行速度快(因为它们会根据序列的大小自动选择实际的命令)而且使用起来更方便。代码如下所示: import pdipdi.find(s, 2) penguinpdi.findall(s, 4) Index([cat, dog], dtypeobject) 缺失值 Pandas开发人员特别关注缺失值。通常你通过向read_csv提供一个标志来接收一个带有NaNs的dataframe。否则可以在构造函数或赋值运算符中使用None(尽管不同数据类型的实现略有不同但它仍然有效)。这张图片有助于解释这个概念: 你可以使用NaNs做的第一件事是了解你是否有NaNs。从上图可以看出isna()生成了一个布尔数组而.sum()给出了缺失值的总数。 现在你知道了它们的存在你可以选择用常量值填充它们或通过插值来一次性删除它们如下所示: 另一方面你可以继续使用它们。大多数Pandas函数会很高兴地忽略缺失值如下图所示: 更高级的函数(median、rank、quantile等)也可以做到这一点。 算术运算与索引对齐: 如果索引中存在非唯一值则结果不一致。不要对索引不唯一的序列使用算术运算。 比较 比较有缺失值的数组可能会比较棘手。下面是一个例子: np.all(pd.Series([1., None, 3.]) pd.Series([1., None, 3.])) Falsenp.all(pd.Series([1, None, 3], dtypeInt64) pd.Series([1, None, 3], dtypeInt64)) Truenp.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_nanTrue) Truelen(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_nanTrue) TypeError ...len(df.compare(df)) 0 True 追加、插入、删除 虽然Series对象被认为是size不可变的但它可以在原地追加、插入和删除元素但所有这些操作都是: 慢因为它们需要为整个对象重新分配内存和更新索引。 非常不方便。 下面是插入值的一种方式和删除值的两种方式: 第二种删除值的方法(通过drop)比较慢并且在索引中存在非唯一值时可能会导致复杂的错误。 Pandas有df.insert方法但它只能将列(而不是行)插入到dataframe中(并且对series不起作用)。 添加和插入的另一种方法是使用iloc对DataFrame进行切片应用必要的转换然后使用concat将其放回。我实现了一个名为insert的函数可以自动执行这个过程: 注意(就像在df.insert中一样)插入位置由位置0ilen(s)指定而不是索引中元素的标签。如下所示: 要按元素的名称插入可以合并pdi。用pdi查找。插入如下所示: 请注意unlikedf.insert、pdi.insert返回一个副本而不是原地修改Series/DataFrame 统计数据 Pandas提供了全方位的统计函数。它们可以让您了解百万元素序列或DataFrame中的内容而无需手动滚动数据。 所有Pandas统计函数都会忽略NaNs如下所示: 注意Pandas std给出的结果与NumPy std不同如下所示: pd.Series([1, 2]).std() 0.7071067811865476pd.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)如下图所示: 下面是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滚动窗口、加权窗口和指数加权窗口 重复数据 在检测和处理重复数据时需要特别小心如下图所示: drop_duplicates和duplication可以保留最后一次出现的副本而不是第一次出现的副本。 请注意s.a uint()比np快。唯一性(O(N) vs O(NlogN))它会保留顺序而不会返回排序结果。独特的。 缺失值被视为普通值有时可能会导致令人惊讶的结果。 如果你想排除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一样查询它以获得每个组的某个属性如下图所示: 在这个例子中我们根据数值除以10的整数部分将序列分成三组。对于每个组我们请求每个组中元素的和、元素的数量以及平均值。 除了这些聚合函数您还可以根据特定元素在组中的位置或相对值访问它们。如下所示: 你也可以使用g.ag ([min max])一次调用计算多个函数或者使用g.c describe()一次显示一堆统计函数。 如果这些还不够你还可以通过自己的Python函数传递数据。它可以是: 一个函数f它接受一个组x(一个Series对象)并生成一个值(例如sum())与g.eapply (f)一起使用。 一个函数f它接受一个组x(一个Series对象)并与g.transform(f)生成一个大小与x相同的Series对象(例如cumsum())。 在上面的例子中输入数据是有序的。groupby不需要这样做。实际上如果分组中的元素不是连续存储的它也同样有效因此它更接近于collections.defaultdict而不是itertools.groupby。它总是返回一个没有重复项的索引。 与defaultdict和关系数据库GROUP BY子句不同Pandas groupby按组名对结果进行排序。可以用sortFalse来禁用它。 免责声明:实际上g.apply(f)比上面描述的更通用: 如果f(x)返回与x大小相同的序列它可以模拟transform 如果f(x)返回一系列不同大小或不同的dataframe则会得到一个具有相应多索引的序列。 但文档警告说这些使用方法可能比相应的transform和agg方法慢所以要小心。 第三部分. DataFrames Pandas的主要数据结构是DataFrame。它将一个二维数组与它的行和列的标签捆绑在一起。它由一系列对象组成(具有共享索引)每个对象表示一列可能具有不同的dtype。 读写CSV文件 构造DataFrame的一种常用方法是读取csv(逗号分隔值)文件如下图所示: pd.read_csv()函数是一个完全自动化且可疯狂定制的工具。如果你只想学习Pandas的一件事那就学习使用read_csv——它会有回报的:)。 下面是一个解析非标准的.csv文件的例子: 以及一些简要描述: 因为CSV没有严格的规范所以有时需要一些试错才能正确地阅读它。read_csv最酷的地方在于它会自动检测很多东西: 列名和类型 布尔值的表示 缺失值的表示等。 与其他自动化一样你最好确保它做了正确的事情。如果在Jupyter单元中简单地编写df的结果碰巧太长(或太不完整)您可以尝试以下操作: df.head(5)或df[:5]显示前5行 df.dtypes返回列的类型 df.shape返回行数和列数 Df.info()汇总所有相关信息 将一列或几列设置为索引是一个好主意。下图展示了这个过程: Index在Pandas中有很多用途: 算术运算按索引对齐 它使按该列进行的查找更快等等。 所有这些都是以较高的内存消耗和不太明显的语法为代价的。 构建DataFrame 另一种选择是从内存中已经存储的数据中构建一个dataframe。它的构造函数非常全能可以转换(或包装)任何类型的数据: 在第一种情况下在没有行标签的情况下Pandas用连续的整数标记行。在第二种情况下它对行和列都进行了相同的操作。为Pandas提供列的名称总是一个好主意而不是整数标签(使用columns参数)有时也可以提供行(使用index参数尽管rows听起来可能更直观)。这张图片会有帮助: 不幸的是无法在DataFrame构造函数中为索引列设置名称所以唯一的选择是手动指定例如df.index.name 城市名称 下一种方法是使用NumPy向量组成的字典或二维NumPy数组构造一个DataFrame: 请注意在第二种情况下人口数量的值被转换为浮点数。实际上它在之前的构建NumPy数组时就发生过。这里需要注意的另一件事是从2D NumPy数组构建dataframe默认是视图。这意味着改变原始数组中的值会改变dataframe反之亦然。另外它节省了内存。 第一种情况(NumPy向量组成的字典)也可以启用这种模式设置copyFalse即可。不过它非常脆弱。简单的操作就可以把它变成副本而不需要通知。 另外两个(不太有用的)创建DataFrame的选项是: 从一个dict列表(其中每个dict表示一行其键是列名其值是相应的单元格值) 来自由Series组成的dict(其中每个Series表示一列;默认情况下可以让它返回一个copyFalse的视图)。 如果你“动态”注册流数据最好的选择是使用列表的dict或列表的列表因为Python会透明地在列表末尾预分配空间以便快速追加。NumPy数组和Pandas dataframes都不能做到这一点。另一种可能性(如果你事先知道行数)是用DataFrame(np.zeros)之类的东西手动预分配内存。 DataFrames的基本操作 DataFrame最好的地方(在我看来)是你可以: 轻松访问其列如d.area返回列值(或者df[ Area ]——适用于包含空格的列名) 将列作为自变量进行操作例如使用afterdf. population / 10**6人口以百万计存储下面的命令根据现有列中的值创建一个名为 density 的新列。更多信息见下图: 注意创建新列时即使列名中不包含空格也必须使用方括号。 此外你可以对不同dataframe中的列使用算术操作只要它们的行具有有意义的标签如下所示: 索引DataFrames 正如我们在本系列中已经看到的普通的方括号不足以满足索引的所有需求。你不能通过名称访问行不能通过位置索引访问不相交的行你甚至不能引用单个单元格因为df[x y]是为多索引保留的! 为了满足这些需求dataframes就像series一样有两种可选的索引模式:按标签索引的loc和按位置索引的iloc。 在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上(会相应地显示一个警告)。 根据不同的背景有不同的解决方案: 你想要改变原始的df。然后使用df。loc[ a: b a] 10 你故意创建了一个副本然后想要处理这个副本:df1 df.loc[ a : b ];df1[ A ]10 # SettingWithCopy warning要在这种情况下消除警告请使其成为一个真正的副本:df1 df.loc[ A : b ].copy();df1 [A] 10 Pandas还支持一种方便的NumPy语法来进行布尔索引。 当使用多个条件时必须将它们括起来如下所示: 当你期望返回一个值时需要特别注意。 因为可能有多行匹配条件所以loc返回一个序列。要从中得到标量值你可以使用: float(s)或更通用的s.e item()除非序列中只有一个值否则都会引发ValueError S.iloc[0]仅在没有找到时引发异常;此外它是唯一支持赋值的函数:df[…].Iloc[0] 100但当你想修改所有匹配时肯定不需要它:df[…] 100。 或者你可以使用基于字符串的查询: df.query ( name “Vienna”) df.query(population1e6 and area1000)它们更短适合多索引并且逻辑操作符优先于比较操作符(需要更少的括号)但它们只能按行过滤并且不能通过它们修改Dataframe。 几个第三方库允许你使用SQL语法直接查询dataframe (duckdb)或者通过将dataframe复制到SQLite并将结果包装回Pandas objects (pandasql)来间接查询dataframe。不出所料直接法更快。 DataFrame算术 你可以对dataframes、series和它们的组合应用普通操作如加、减、乘、除、求模、幂等。 所有的算术运算都是根据行标签和列标签对齐的: 在dataframe和Series之间的混合操作中Series(天知道为什么)表现得(和广播)像一个行向量并相应地对齐: 可能是为了与列表和一维NumPy向量保持一致(它们不按标签对齐并被认为是一个简单的二维NumPy数组的DataFrame): 因此在不太幸运(也是最常见的!)的情况下将一个dataframe除以列向量序列你必须使用方法而不是操作符如下所示: 由于这个有问题的决定每当你需要在dataframe和列式序列之间执行混合操作时你必须在文档中查找它(或记住它): 结合DataFrames Pandas有三个函数concat、merge和join它们做同样的事情:将来自多个dataframe的信息合并为一个。但是每个工具的实现方式都略有不同因为它们是为不同的用例量身定制的。 垂直叠加 这可能是将两个或多个dataframe合并为一个的最简单方法:您获取第一个dataframe中的行并将第二个dataframe中的行追加到底部。为了使其工作这两个dataframe需要(大致)具有相同的列。这类似于NumPy中的vstack正如你在图像中所看到的: 索引中有重复的值是不好的。你可能会遇到各种各样的问题(参见下面的 drop 示例)。即使你不关心索引也要尽量避免出现重复的值: 要么使用reset_indexTrue参数 调用df.reset_index(dropTrue)将行从0重新索引到len(df)-1 使用keys参数可以解决MultiIndex的二义性(见下文)。 如果dataframe的列不能完美匹配(不同的顺序在这里不计算在内)Pandas可以取列的交集(默认值kindinner )或插入nan来标记缺失值(kindouter): 水平叠加 concat也可以执行“水平”堆叠(类似于NumPy中的hstack): join比concat更可配置:特别是它有五种连接模式而concat只有两种。详情请参阅下面的“1:1关系连接”部分。 基于多指数的数据叠加 如果行标签和列标签一致concat可以执行与垂直堆叠类似的多索引(就像NumPy中的dstack): 如果行和/或列部分重叠Pandas将相应地对齐名称这很可能不是你想要的。下面的图表可以帮助你将这个过程可视化: 一般来说如果标签重叠这意味着dataframe在某种程度上彼此相关实体之间的关系最好使用关系数据库的术语来描述。 1:1 连接的关系 当同一组对象的信息存储在几个不同的DataFrame中时你希望将它们合并为一个DataFrame。 如果要合并的列不在索引中则使用merge。 它所做的第一件事是丢弃索引中的任何内容。然后执行联结操作。最后将结果从0重新编号为n-1。 如果列已经在索引中则可以使用join(这只是merge的别名将left_index或right_index设置为True并设置不同的默认值)。 从这个简化的例子中可以看出(参见上面的全外连接)与关系型数据库相比Pandas对行顺序的处理相当轻松。左外联结和右外联结比内外联结更容易预测(至少在需要合并的列中有重复值之前是这样)。因此如果你想保证行顺序就必须显式地对结果进行排序。 1:n 连接的关系 这是数据库设计中使用最广泛的关系表A中的一行(例如“State”)可以与表B中的几行(例如城市)相关联但表B中的每一行只能与表A中的一行相关联(即一个城市只能处于一种状态但一个状态由多个城市组成)。 就像1:1关系一样在Pandas中连接一对1:n相关的表你有两种选择。如果要合并的列或者不在索引中并且可以丢弃碰巧在两张表的索引中都存在的列则使用merge。下面的例子会有所帮助: 正如我们已经看到的merge对行顺序的处理没有Postgres严格:所有声明的语句保留的键顺序只适用于left_indexTrue和/或right_indexTrue(这就是join的别名)并且只在要合并的列中没有重复值的情况下。这就是为什么join有一个sort参数。 现在如果要合并的列已经在右侧DataFrame的索引中可以使用join(或者merge with right_indexTrue这是完全相同的事情): 这次Pandas保留了左DataFrame的索引值和行顺序。 注意:注意如果第二个表有重复的索引值你最终将在结果中得到重复的索引值即使左表索引是唯一的! 有时合并的dataframe具有同名的列。merge和join都有解决二义性的方法但语法略有不同(默认情况下merge会用 _x _y 来解决而join会抛出异常)如下图所示: 总结: 合并非索引列上的连接连接要求列被索引 merge丢弃左DataFrame的索引join保留它 默认情况下merge执行内联结join执行左外联结 合并不保持行顺序 Join可以保留它们(有一些限制) join是合并的别名left_indexTrue和/或right_indexTrue 多个连接 如上所述当对两个dataframe(如df.join(df1))运行join时它充当了合并的别名。但是join也有一个 multiple join 模式它只是concat(axis1)的别名。 与普通模式相比该模式有一些限制: 它没有提供解析重复列的方法 它只适用于1:1关系(索引到索引连接)。 因此多个1:n关系应该一个接一个地连接。仓库 panda -illustrated 也提供了一个辅助方法如下所示: pdi.join是Join的一个简单包装器它接受on、how和后缀参数以便您可以在一个命令中进行多个联结。与原始的关联操作一样关联的是属于第一个DataFrame的列其他DataFrame根据它们的索引进行关联操作。 插入和删除 由于DataFrame是列的集合因此将这些操作应用到行上比应用到列上更容易。例如插入一列总是在原地完成而插入一行总是会生成一个新的DataFrame如下所示: 删除列通常不用担心除了del df[D]和del df。D则没有(Python级别的限制)。 使用drop删除行非常慢如果原始标签不是唯一的可能会导致复杂的bug。下图将帮助解释这个概念: 一种解决方案是使用ignore_indexTrue它告诉concat在连接后重置行名称: 在这种情况下将name列设置为索引将有所帮助。但对于更复杂的滤波器它不会。 另一种快速、通用、甚至可以处理重复行名的解决方案是索引而不是删除。为了避免显式地否定条件我写了一个(只有一行代码的)自动化程序。 分组 这个操作已经在Series部分详细描述过了。但是DataFrame的groupby在此基础上有一些特定的技巧。 首先你可以使用一个名称来指定要分组的列如下图所示: 如果没有as_indexFalse, Pandas将进行分组的列指定为索引。如果这不是我们想要的可以使用reset_index()或指定as_indexFalse。 通常数据框中的列比你想在结果中看到的多。默认情况下Pandas会对所有远端可求和的东西进行求和因此你需要缩小选择范围如下所示: 注意当对单个列求和时你将得到一个Series而不是DataFrame。如果出于某种原因你想要一个DataFrame你可以: 使用双括号:df.groupby(product)[[quantity]].sum() 显式转换:df.groupby(product)[quantity].sum().to_frame() 切换到数值索引也会创建一个DataFrame: df.groupby(product, as_indexFalse)[quantity].sum() df.groupby(product)[quantity].sum().reset_index() 但是尽管外观不寻常Series的行为就像DataFrames一样所以可能对pdi.patch_series_repr()进行“整容”就足够了。 显然不同的列在分组时表现不同。例如对数量求和完全没问题但对价格求和就没有意义了。使用。agg可以为不同的列指定不同的聚合函数如下图所示: 或者你可以为一列创建多个聚合函数: 或者为了避免繁琐的列重命名你可以这样做: 有时预定义的函数不足以产生所需的结果。例如在平均价格时使用权重会更好。你可以为此提供一个自定义函数。与Series不同的是该函数可以访问组中的多个列(它以子dataframe作为参数)如下所示: 不幸的是你不能把预定义的聚合和几个列级的自定义函数结合在一起比如上面的那个因为agg只接受单列级的用户函数。单列范围的用户函数唯一可以访问的是索引这在某些情况下很方便。例如那天香蕉以5折的价格出售如下图所示: 为了从自定义函数中访问group by列的值它事先已经包含在索引中。 通常定制最少的函数可以获得最好的性能。为了提高速度: 通过g.apply()实现多列范围的自定义函数 通过g.agg()实现单列范围的自定义函数(支持使用Cython或Numba进行加速) 预定义函数(Pandas或NumPy函数对象或其字符串名称)。 预定义函数(Pandas或NumPy函数对象或其字符串名称)。 数据透视表(pivot table)是一种有用的工具通常与分组一起使用从不同的角度查看数据。 旋转和反旋转 假设你有一个变量a它依赖于两个参数i和j。有两种等价的方法将它表示为一个表: 当数据是“密集的”(当有很少的0元素)时 short 格式更合适而当数据是“稀疏的”(大多数元素为0可以从表中省略)时 long 格式更好。当有两个以上的参数时情况会变得更加复杂。 当然应该有一种简单的方法来转换这些格式。Pandas为此提供了一个简单方便的解决方案:数据透视表。 作为一个不那么抽象的例子考虑下表中的销售数据。有两个客户购买了两种产品的指定数量最初这个数据是短格式的。要将其转换为长格式请使用df.pivot: 该命令丢弃了与操作无关的任何信息(索引、价格)并将来自三个请求列的信息转换为长格式将客户名称放入结果的索引中将产品名称放入列中将销售数量放入DataFrame的 body 中。 至于相反的操作你可以使用stack。它将索引和列合并到MultiIndex中: 另一种选择是使用melt: 注意melt以不同的方式对结果行进行排序。 Pivot丢失了结果的 body 的名称信息因此无论是stack还是melt我们都必须提醒pandas quantity 列的名称。 在上面的例子中所有的值都存在但这不是必须的: 分组值然后旋转结果的做法是如此常见以至于groupby和pivot被捆绑在一个专用的函数(以及相应的DataFrame方法)数据透视表中: 如果没有columns参数它的行为与groupby类似 当没有重复的行进行分组时它的工作原理与pivot类似 否则它会进行分组和旋转 aggfunc参数控制哪一个聚合函数应该用于分组行(默认为均值)。 为了方便pivot_table可以计算小计和合计: 一旦创建pivot表就变成了一个普通的DataFrame因此可以使用前面描述的标准方法查询它。 当使用多索引时透视表特别方便。我们已经见过很多Pandas函数返回多索引DataFrame的例子。让我们仔细看看。 第四部分. MultiIndex 对于从未听说过Pandas的人来说多索引MultiIndex最直接的用法是使用第二个索引列作为第一个索引列的补充以唯一地标识每行。例如为了消除来自不同州的城市的歧义州的名字通常附加在城市的名字后面。例如在美国大约有40个springfield(在关系型数据库中它被称为复合主键)。 你可以在从CSV解析DataFrame后指定要包含在索引中的列也可以立即作为read_csv的参数。 您还可以使用appendTrue将现有级别添加到多重索引如下图所示: 另一个更典型的用例是表示多维。当你有一组具有特定属性的对象或者随着时间的推移而演变的对象时。例如: 社会学调查的结果 Titanic 数据集 历史天气观测 锦标赛排名的年表。 这也被称为“面板数据”Pandas就是以此命名的。 让我们添加这样一个维度: 现在我们有了一个四维空间如下所示: 年形成一个(几乎连续的)维度 城市名称沿第二条排列 第三个州的名字 特定的城市属性(“人口”、“密度”、“面积”等)在第四个维度上起到了“刻度线”的作用。 下图说明了这个概念: 为了给对应列的尺寸名称留出空间Pandas将整个标题向上移动: 分组 关于多重索引需要注意的第一件事是它并不按照它可能出现的情况对任何内容进行分组。在内部它只是一个扁平的标签序列如下所示: 你可以通过对行标签进行排序来获得相同的groupby效果: 你甚至可以通过设置相应的Pandas选项来完全禁用视觉分组 :pd.options.display.multi_sparseFalse。 类型转换 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), level0) 但为了正确使用它们你需要理解什么是 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自己的多索引表示的最直观的方法不起作用。 这里的 Levels 和 codes (现在)被认为是不应该暴露给最终用户的实现细节但我们已经拥有了我们所拥有的。 可能最简单的构建多重索引的方法如下: 这样做的缺点是必须在单独的一行中指定级别的名称。有几种可选的构造函数将名称和标签捆绑在一起。 当关卡形成规则结构时您可以指定关键元素并让Pandas自动交织它们如下所示: 上面列出的所有方法也适用于列。例如: 使用多重索引进行索引 通过多重索引访问DataFrame的好处是您可以轻松地使用熟悉的语法一次引用所有级别(可能省略内部级别)。 列——通过普通的方括号 行和单元格——使用.loc[] 现在如果你想选择俄勒冈州的所有城市或者只留下包含人口的列该怎么办?Python语法在这里有两个限制。 1. 没有办法区分df[a b]和df[(a b)]——它是以同样的方式处理的所以你不能只写df[: Oregon ]。否则Pandas将永远不知道你指的是列Oregon还是第二级行Oregon 2. Python只允许在方括号内使用冒号而不允许在圆括号内使用冒号所以你不能写df.loc[(: Oregon):] 在技术方面这并不难安排。我给DataFrame打了猴补丁添加了这样的功能你可以在这里看到: 这种语法唯一的缺点是当你使用两个索引器时它返回一个副本所以你不能写df.mi[: Oregon ]。Co [ population ] 10。有许多可选的索引器其中一些允许这样的赋值但它们都有自己的特点: 1. 您可以将内层与外层交换并使用括号。 因此df[: population]可以用df.swaplevel(axis1)[population]实现。 这感觉很hacky不方便超过两层。 2. 你可以使用xs方法:df.xs ( population level1, axis1)。 它给人的感觉不够python化尤其是在选择多个关卡时。这种方法无法同时过滤行和列因此名称xs(代表“横截面”)背后的原因并不完全清楚。它不能用于设置值。 3.可以为pd创建别名。idxpd.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( stateOregon or cityPortland )。 它方便快捷但缺乏IDE的支持(没有自动补全没有语法高亮等)而且它只过滤行而不是列。这意味着你不能在不转置DataFrame的情况下用它实现df[: population ](除非所有列的类型都相同否则会丢失类型)。Non-writable。 叠加与拆分 Pandas没有针对列的set_index。向列中添加层次的一种常见方法是将现有的层次从索引中“解栈”: Pandas的栈与NumPy的栈有很大不同。让我们看看文档中对命名约定的说明: “该函数的命名类似于重新组织的书籍集合从水平位置并排(dataframe的列)到垂直堆叠(在dataframe的索引中)。” “在上面”的部分听起来并不能让我信服但至少这个解释有助于记住谁把东西朝哪个方向移动。顺便说一下Series有unstack但没有stack因为它已经“堆叠”了。由于是一维的Series在不同情况下可以作为行向量或列向量但通常被认为是列向量(例如dataframe列)。 例如: 您还可以通过名称或位置索引指定要堆叠/解堆叠的级别。在这个例子中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) 列必须不包含重复的值才能堆叠(在反堆叠时索引也是如此): 如何防止叠加/分解排序 stack和unstack都有一个坏习惯会不可预测地按字典顺序排序结果索引。这有时可能令人恼火但这是在有大量缺失值时给出可预测结果的唯一方法。 考虑下面的例子。你希望一周中的天数以何种顺序出现在右边的表中? 你可以推测如果John的星期一在John的星期五的左边那么就是 Mon Fri 类似地Silvia的 Fri Sun 因此结果应该是 Mon Fri Sun 。这是合法的但是如果剩余的列顺序不同比如 Mon frii 和 Tue frii 该怎么办?或者 Mon friday 和 Wed Sat ? 好吧一周没有那么多天Pandas可以根据先验知识推断出顺序。但是人类还没有得出一个决定性的结论那就是星期天应该作为一周的结束还是开始。Pandas应该默认使用哪种顺序?阅读区域设置?那么不那么琐碎的顺序呢比如美国的州的顺序? 在这种情况下Pandas所做的只是简单地按字母顺序排序如下所示: 虽然这是一个合理的默认但感觉上仍然是错误的。应该有一个解决方案!有一个。它被称为CategoricalIndex。即使缺少一些标签它也会记住顺序。它最近已经顺利集成到Pandas工具链中。它唯一缺少的是基础设施。它很难建立;它是脆弱的(在某些操作中会退回到对象)但它是完全可用的并且pdi库有一些帮助程序可以陡峭地提高学习曲线。 例如要告诉Pandas锁定存储产品的简单索引的顺序(如果你决定将一周中的天数解栈回列则不可避免地会排序)你需要编写像df这样可怕的代码。index pd.CategoricalIndex(df. index)df指数。指数排序 True)。它更适合多索引。 pdi库有一个辅助函数locked(以及一个默认为inplaceTrue的别名lock)通过将某个多索引级别提升到CategoricalIndex来锁定该级别的顺序: 等级名称旁边的勾选标记表示等级被锁定。它可以使用pdi.vis(df)手动可视化也可以使用pdi.vis_patch()对DataFrame HTML输出进行monkey补丁自动可视化。应用补丁后在Jupyter单元中简单地写 df 将显示锁定顺序的所有级别的复选标记。 Lock和locked在简单的情况下自动工作(如客户端名称)但在更复杂的情况下(如缺少日期的星期几)需要用户提示。 在级别切换到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等)替换关卡的标签 pdi.insert_level (obj, pos, labels, name)使用给定的值添加一个层级(必要时适当广播) pdi.drop_level(obj, level_id)从多重索引中删除指定的级别 pdi.swap_levels (obj, src-2, dst-1)交换两个级别(默认是两个最内层的级别) pdi.move_level (obj, src, dst)将特定级别src移动到指定位置dst 除了上述参数外本节中的所有函数还有以下参数: axisNone其中None对于DataFrame表示“列”对于Series表示“索引” sortFalse可选在操作之后对相应的多索引进行排序 inplaceFalse可选地原地执行操作(不能用于单个索引因为它是不可变的)。 上面的所有操作都是从传统意义上理解“级别”这个词的(级别的标签数量与数据框中的列数量相同)隐藏了索引的机制。标签和索引。来自最终用户的代码。 在极少数情况下当移动和交换单独的关卡不够时您可以使用纯Pandas调用:df一次性重新排序所有关卡。columns df.columns.reorder_levels([ M L K ])其中[ M L K ]是层的期望顺序。 通常使用get_level和set_level对标签进行必要的修复就足够了但如果你想一次对多索引的所有级别应用转换Pandas有一个(命名不明确)函数rename接受一个dict或一个函数: 至于重命名级别它们的名称存储在.names字段中。该字段不支持直接赋值(为什么不?):df.index.names[1] x # TypeError但可以作为一个整体替换: 当你只需要重命名一个特定的级别时语法如下: 将多索引转换为平面索引并恢复它 正如我们在上面看到的便捷的查询方法只解决了处理行中的多索引的复杂性。尽管有这么多的辅助函数但当某些Pandas函数返回列中的多索引时对初学者来说会有一个震惊的效果。因此pdi库具有以下内容: join_levels(obj, sep’_’, nameNone) 将所有多索引级别连接到一个索引 split_level(obj, sep’_’, namesNone)将索引拆分回多索引 它们都有可选的axis和inplace参数。 排序MultiIndex 由于多索引由多个级别组成因此排序比单索引更做作。这仍然可以使用sort_index方法完成但可以使用以下参数进行进一步微调。 要对列级别进行排序指定axis1。 读写多索引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算术 当使用多索引数据框时与普通数据框适用相同的规则(见上文)。但是处理细胞的一个子集有它自己的一些特性。 用户可以通过外部的多索引级别更新部分列如下所示: 如果想保持原始数据不变可以使用df1 df.assign(populationdf.population*10)。 你也可以用densitydf.population/df.area轻松获得人口密度。 但不幸的是你不能用df.assign将结果赋值给原始的dataframe。 一种方法是将列索引的所有不相关级别堆叠到行索引中执行必要的计算然后将它们解堆叠回去(使用pdi)。锁以保持列的原始顺序)。 或者你也可以使用pdi.assign: pdi.assign是锁定顺序感知的所以如果你给它一个(多个)锁定级别的dataframe它不会解锁它们或后续的栈/解栈/等。操作将保持原始的列和行顺序。 总而言之Pandas是分析和处理数据的好工具。希望这篇文章能帮助你理解“如何”和“为什么”解决典型问题并欣赏Pandas库的真正价值和美丽。
http://www.yingshimen.cn/news/114539/

相关文章:

  • 免费推广产品的网站寿光做网站m0536
  • 做地区招聘网站微信公众号商城怎么制作
  • 做受视频播放网站文学写作网站
  • 岳阳市城市建设投资公司网站网站建设运营合同书
  • 三网合一网站怎么做东华大学网络教育网页设计作业
  • 一个网站开发的意义那些免费网站可以做国外贸易
  • 微信网站建设咨询网站设计制作是什么
  • 做加盟网站赚钱吗平邑建设银行网站
  • 建设简单网站的图纸虚拟空间应用程序
  • 赚钱的网站做任务照片编辑软件app
  • 做影集的网站或软件担路网络科技有限公司的证书
  • 淘宝联盟怎样做新增网站推广小程序游戏排名
  • wap网站优化怎样进入医院公众号
  • 网站关键词都没有了做表格的网站
  • 网站首页页脚网页赚钱游戏
  • 增城企业网站建设手机购物网站开发
  • 温州市手机网站制作哪家好火山软件开发平台教程
  • 免费奖励自己的网站网站备案流程解答
  • 上海网站se0优化做网站空间备案的职业
  • 姚孟信通网站开发中心什么是vi设计?
  • 宁波网站推广制作公司海南澄迈县
  • 福建省城市建设厅网站常见的网络推广方法有哪些
  • 厦门城乡建设局网站自贡市规划建设局网站
  • qplayer wordpress湘潭专业seo优化价格
  • 巩义网站建设佛山高端网站开发公司
  • 站长统计app网站小程序开发平台到底哪家好
  • 视频网站做电商外贸谷歌网站推广
  • 建德网站建设公司莱芜在线沙总
  • 深圳市住房和建设局网站首页建设部网站资质人员查询
  • 网站建设公司的未来专业的网站制作公司