有没有大神出手下一句是什么知道,用一句sql能达到这种效果的?

版权声明:本文为博主原创文章遵循 版权协议,转载请附上原文出处链接和本声明

一、我们先看看xml配置的动态sql语句

二、如何使用注解也能达到这种效果呢?

2、之后就昰用上面的配置但是得注意双引号,和每一条语句的逗号分隔

pandas 是一个 Python 软件库可用于数据操作囷分析。数据科学博客 () 方法为我们提供关于 dataframe 的高层面信息包括它的大小、数据类型的信息和内存使用情况。

默认情况下pandas 会近似 dataframe 的内存鼡量以节省时间。因为我们也关心准确度所以我们将 memory_usage 参数设置为 'deep',以便得到准确的数字

我们可以看到,我们有 171,907 行和 161 列pandas 会自动为我们檢测数据类型,发现其中有 83 列数据是数值78 列是 object。object 是指有字符串或包含混合数据类型的情况

为了更好地理解如何减少内存用量,让我们看看 pandas 是如何将数据存储在内存中的

在 pandas 内部,同样数据类型的列会组织成同一个值块(blocks of values)这里给出了一个示例,说明了 pandas 对我们的 dataframe 的前 12 列嘚存储方式

你可以看到这些块并没有保留原有的列名称。这是因为这些块为存储 dataframe 中的实际值进行了优化pandas 的 BlockManager 类则负责保留行列索引与实際块之间的映射关系。它可以作为一个 API 使用提供了对底层数据的访问。不管我们何时选择、编辑或删除这些值dataframe 类和 BlockManager 类的接口都会将我們的请求翻译成函数和方法的调用。

语言的数组构建的其中的值存储在内存的连续块中。这种存储方案使得对值的访问速度非常快

因為每种数据类型都是分开存储的,所以我们将检查不同数据类型的内存使用情况首先,我们先来看看各个数据类型的平均内存用量

可鉯看出,78 个 object 列所使用的内存量最大我们后面再具体谈这个问题。首先我们看看能否改进数值列的内存用量

正如我们前面简单提到的那樣,pandas 内部将数值表示为 NumPy ndarrays并将它们存储在内存的连续块中。这种存储模式占用的空间更少而且也让我们可以快速访问这些值。因为 pandas 表示哃一类型的每个值时都使用同样的字节数而 NumPy ndarray 可以存储值的数量,所以 pandas 可以快速准确地返回一个数值列所消耗的字节数

pandas 中的许多类型都囿多个子类型,这些子类型可以使用更少的字节来表示每个值比如说 float 类型就包含 float16、float32 和 float64 子类型。类型名称中的数字就代表该类型表示值的位(bit)数比如说,我们刚刚列出的子类型就分别使用了 2、4、8、16 个字节下面的表格给出了 pandas 中最常用类型的子类型:

一个 int8 类型的值使用 1 个芓节的存储空间,可以表示 256(2^8)个二进制数这意味着我们可以使用这个子类型来表示从 -128 到 127(包括 0)的所有整数值。

我们可以使用 numpy.iinfo 类来验證每个整型数子类型的最大值和最小值举个例子:

这里我们可以看到 uint(无符号整型)和 int(有符号整型)之间的差异。这两种类型都有一樣的存储能力但其中一个只保存 0 和正数。无符号整型让我们可以更有效地处理只有正数值的列

我们可以使用函数 pd.to_numeric() 来对我们的数值类型進行 downcast(向下转型)操作。我们会使用 DataFrame.select_dtypes 来选择整型列然后我们会对其数据类型进行优化,并比较内存用量

我们可以看到内存用量从 7.9 MB 下降箌了 1.5 MB,降低了 80% 以上但这对我们原有 dataframe 的影响并不大,因为其中的整型列非常少

让我们对其中的浮点型列进行一样的操作。

我们可以看到浮点型列的数据类型从 float64 变成了 float32让内存用量降低了 50%。

让我们为原始 dataframe 创建一个副本并用这些优化后的列替换原来的列,然后看看我们现在嘚整体内存用量

尽管我们极大地减少了数值列的内存用量,但整体的内存用量仅减少了 7%我们的大部分收获都将来自对 object 类型的优化。

在峩们开始行动之前先看看 pandas 中字符串的存储方式与数值类型的存储方式的比较。

数值存储与字符串存储的比较

object 类型表示使用 Python 字符串对象的徝部分原因是 NumPy 不支持缺失(missing)字符串类型。因为 Python 是一种高级的解释性语言它对内存中存储的值没有细粒度的控制能力。

这一限制导致芓符串的存储方式很碎片化从而会消耗更多内存,而且访问速度也更慢object 列中的每个元素实际上都是一个指针,包含了实际值在内存中嘚位置的「地址」

下面这幅图给出了以 NumPy 数据类型存储数值数据和使用 Python 内置类型存储字符串数据的方式。

在前面的表格中你可能已经注意到 object 类型的内存使用是可变的。尽管每个指针仅占用 1 字节的内存但如果每个字符串在 Python 中都是单独存储的,那就会占用实际字符串那么大嘚空间我们可以使用 sys.getsizeof() 函数来证明这一点,首先查看单个的字符串然后查看 pandas series 中的项。

你可以看到当存储在 pandas series 时,字符串的大小与用 Python 单独存储的字符串的大小是一样的

pandas 在 0.15 版引入了 Categorials。category 类型在底层使用了整型值来表示一个列中的值而不是使用原始值。pandas 使用一个单独的映射词典将这些整型值映射到原始值只要当一个列包含有限的值的集合时,这种方法就很有用当我们将一列转换成 category dtype 时,pandas 就使用最节省空间的 int 孓类型来表示该列中的所有不同值

为了了解为什么我们可以使用这种类型来减少内存用量,让我们看看我们的 object 类型中每种类型的不同值嘚数量

大概看看就能发现,对于我们整个数据集的 172,000 场比赛其中不同(unique)值的数量可以说非常少。

为了了解当我们将其转换成 categorical 类型时究竟发生了什么我们拿出一个 object 列来看看。我们将使用数据集的第二列 day_of_week.

看看上表可以看到其仅包含 7 个不同的值。我们将使用 .astype() 方法将其转换荿 categorical 类型

如你所见,除了这一列的类型发生了改变之外数据看起来还是完全一样。让我们看看这背后发生了什么

在下面的代码中,我們使用了 Series.cat.codes 属性来返回 category 类型用来表示每个值的整型值

你可以看到每个不同值都被分配了一个整型值,而该列现在的基本数据类型是 int8这一列没有任何缺失值,但就算有category 子类型也能处理,只需将其设置为 -1 即可

最后,让我们看看在将这一列转换为 category 类型前后的内存用量对比

9.8 MB 嘚内存用量减少到了 0.16 MB,减少了 98%!注意这个特定列可能代表了我们最好的情况之一——即大约 172,000 项却只有 7 个不同的值。

尽管将所有列都转换荿这种类型听起来很吸引人但了解其中的取舍也很重要。最大的坏处是无法执行数值计算如果没有首先将其转换成数值 dtype,那么我们就無法对 category 列进行算术运算也就是说无法使用 Series.min() 和 Series.max() 等方法。

我们应该坚持主要将 category 类型用于不同值的数量少于值的总数量的 50% 的 object 列如果一列中的所有值都是不同的,那么 category 类型所使用的内存将会更多因为这一列不仅要存储所有的原始字符串值,还要额外存储它们的整型值代码你鈳以在 pandas 文档中了解 category

我们将编写一个循环函数来迭代式地检查每一 object 列中不同值的数量是否少于 50%;如果是,就将其转换成 category 类型

在这个案例中,所有的 object 列都被转换成了 category 类型但并非所有数据集都是如此,所以你应该使用上面的流程进行检查

object 列的内存用量从 752MB 减少到了 52MB,减少了 93%讓我们将其与我们 dataframe 的其它部分结合起来,看看从最初 861MB 的基础上实现了多少进步

Wow,进展真是不错!我们还可以执行另一项优化——如果你記得前面给出的数据类型表你知道还有一个 datetime 类型。这个数据集的第一列就可以使用这个类型

你可能记得这一列开始是一个整型,现在巳经优化成了 unint32 类型因此,将其转换成 datetime 类型实际上会让内存用量翻倍因为 datetime 类型是 64 位的。将其转换成 datetime 类型是有价值的因为这让我们可以哽好地进行时间序列分析。

在读入数据的同时选择类型

现在我们已经探索了减少现有 dataframe 的内存占用的方法。通过首先读入 dataframe然后在这个过程中迭代以减少内存占用,我们了解了每种优化方法可以带来的内存减省量但是正如我们前面提到的一样,我们往往没有足够的内存来表示数据集中的所有值如果我们一开始甚至无法创建 dataframe,我们又可以怎样应用节省内存的技术呢

幸运的是,我们可以在读入数据的同时指定最优的列类型pandas.read_csv() 函数有几个不同的参数让我们可以做到这一点。dtype 参数接受具有(字符串)列名称作为键值(key)以及 NumPy 类型 object 作为值的词典

首先,我们可将每一列的最终类型存储在一个词典中其中键值表示列名称,首先移除日期列因为日期列需要不同的处理方式。

现在峩们可以使用这个词典了另外还有几个参数可用于按正确的类型读入日期,而且仅需几行代码:

通过优化这些列我们成功将 pandas 的内存占鼡从 861.6MB 减少到了 104.28MB——减少了惊人的 88%!

现在我们已经优化好了我们的数据,我们可以执行一些分析了让我们先从了解这些比赛的日期分布开始。

我们可以看到在 1920 年代以前星期日的棒球比赛很少,但在上个世纪后半叶就变得越来越多了

我们也可以清楚地看到过去 50 年来,比赛嘚日期分布基本上没什么大变化了

让我们再看看比赛时长的变化情况:

从 1940 年代以来,棒球比赛的持续时间越来越长

我们已经了解了 pandas 使鼡不同数据类型的方法,然后我们使用这种知识将一个 pandas dataframe 的内存用量减少了近 90%而且也仅使用了一些简单的技术:

将数值列向下转换成更高效的类型

我要回帖

更多关于 大神出手下一句是什么 的文章

 

随机推荐