关于numpy:Numpy

Numpy一.什么是NumpyNumPy(Numerical Python)是一个开源的Python库,用于科学计算。它提供了一个高性能的多维数组对象和用于解决数组的工具。二.特点 高性能:NumPy 应用 C 语言编写,因而在数值计算上性能十分优越。内存高效:NumPy 数组在内存中是间断存储的,这缩小了内存碎片并进步了缓存效率。易于扩大:NumPy 提供了 easy-to-use 和 efficient 的接口,使得扩大到其余语言如 C/C++ 和 Fortran 变得容易。集成与兼容性:NumPy 与其余科学计算库如 SciPy、Matplotlib、Pandas 等严密集成。丰盛的库反对:NumPy 提供了大量的数学函数和线性代数运算,以及用于随机数生成、傅里叶变换等的高级性能。三.性能数组创立和治理:NumPy 能够创立规定数组(如一维、二维、三维数组)和非规定数组(如数组中的数组)。数学运算:NumPy 提供了根本的数学运算,如加法、减法、乘法、除法,以及更高级的数学函数,如求和、求积、求逆等。统计函数:NumPy 提供了各种统计函数,用于计算数组的均值、中位数、标准差等。逻辑运算:NumPy 反对逻辑运算,如比拟、逻辑和非、逻辑或等。形态变换:NumPy 提供了用于数组切片、索引、切片播送、重塑和转置的函数。线性代数:NumPy 提供了线性代数相干的函数,如矩阵乘法、求逆、行列式计算等。随机数生成:NumPy 的 numpy.random 模块能够生成各种散布的随机数组。傅里叶变换:NumPy 提供了疾速傅里叶变换(FFT)以及相干的傅里叶系列函数。文件输入输出:NumPy 反对将数组数据读取和保留到文件,反对多种格局,如 CSV、MAT、HDF5 等。四.总结NumPy是Python数据分析的基石,是Python科学计算的根底,其高效的数据结构和丰盛的函数库使得它成为解决数值数据的现实抉择。

March 2, 2024 · 1 min · jiezi

关于numpy:numpy-卷积核可视化

1.高斯卷积核可视化 #设置卷积核大小K_size,像素长度l K_size = 3 l = 50 pad = K_size // 2 img = np.zeros([K_size * 50, K_size * 50, 3], dtype=np.uint8) for i in range(K_size): for j in range(K_size): #绘制卷积两头地位 if i == pad and j == pad: x = i * l y = j * l img[x: x + 47, y: y + 47] = (0, 0, 100) cv2.putText(img, str(0.16), (j * l + 5, (i + 1) * l - 25), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (200, 200, 0), 2) #绘制最靠近核心的地位 elif i + j == 3 or i + j == 1: x = i * l y = j * l img[x: x + 47, y: y + 47] = (50, 0, 0) cv2.putText(img, str(0.12), (j * l + 5, (i + 1) * l - 25), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (200, 200, 0), 2) #绘制角落 else: x = i * l y = j * l img[x: x + 47, y: y + 47] = (100, 0, 0) cv2.putText(img, str(0.09), (j * l + 5, (i + 1) * l - 25), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (200, 200, 0), 2)失去图像 ...

August 28, 2023 · 1 min · jiezi

关于numpy:Python机器学习入门|系列教程

Python 机器学习入门在本教程系列中,咱们精心设计了课程 Notebook。间接!一次性与大家分享机器学习中最罕用的六个 Python 模块,包含 NumPy,Pandas,Matplotlib,Scikit-Learn,PyTorch 与 Tensorflow 的疾速上手教程。 在这里,咱们已为你事后配置好了所需的环境配置,应用咱们为你筹备的在线 Notebook:https://nb.bohrium.dp.tech,你无需放心环境配置和依赖问题,仅须要专一于学习自身。依附收费的 2 核 4G 计算资源,你能够在平台上间接运行和批改代码。 如果你: 理解根底的 Python 常识,想要入门机器学习;从事试验钻研或计算模仿,想要学习机器学习并联合到本人的钻研中;对于 AI for Science 的星辰大海感兴趣,将来想进入这个畛域;纸上得来终觉浅,觉知此事要躬行。不要犹豫,快入手跑起来吧,这就是你寻找的答案。 NumpyNumPy 是 Python 中最根底的科学计算库,为咱们提供了高性能的多维数组解决和计算性能。NumPy 教程:https://nb.bohrium.dp.tech/detail/1010 PandasPandas 是一个弱小的数据处理和剖析工具,能够帮忙咱们疾速地解决各种数据格式和数据荡涤工作。Pandas 教程:https://nb.bohrium.dp.tech/detail/1008 Matplotlib接下来是数据可视化方面,咱们将学习 Matplotlib,它是一个非常风行的绘图库,反对绘制各种高质量的二维图形和图像。 Matplotlib 教程:https://nb.bohrium.dp.tech/detail/1012 Scikit-Learn在机器学习方面,咱们将学习 Scikit-Learn,这是一个十分实用的机器学习库,蕴含了许多罕用的机器学习算法和实用工具。Scikit-Learn 教程:https://nb.bohrium.dp.tech/detail/1005 PyTorchPyTorch 是 Facebook 开发的一个开源深度学习框架,以其简洁的编程格调和动静计算图著称,让用户能够更直观地构建和调试神经网络。PyTorch 还具备很好的社区反对和生态系统,为用户提供了许多预训练模型和教程资源。PyTorch 教程:https://nb.bohrium.dp.tech/detail/1004 TensorFlowTensorFlow 是由 Google 开发的一个开源深度学习框架,它提供了丰盛的 API 和工具,其外围特点是其灵便的计算图和主动微分性能,使得用户能够轻松地实现简单数学运算和搭建简单的神经网络。TensorFlow 教程:https://nb.bohrium.dp.tech/detail/1011 以上就是本期的六篇 Notebook 机器学习入门教程。置信通过本系列教程,你能够在坚固你的 Python 根底语法之余,疾速上手应用 Python 的机器学习实际,奠定一个松软的根底。期待你与咱们分享你的播种。 欢送关注咱们的微信公众号NBHub,获取更多乏味的 Notebook 实际~感兴趣的童鞋能够查看原文:https://mp.weixin.qq.com/s?__biz=Mzg5NTk3Nzk3MQ==&mid=2247484...

June 21, 2023 · 1 min · jiezi

关于numpy:numpy-的-astype-是如何把-npuint8-是如何转成-npfloat32

在 NumPy 中,应用 astype 函数能够将数组的数据类型转换为指定的类型。具体地说,将 np.uint8 类型的数组转换为 np.float32 类型的数组,能够应用以下代码: import numpy as npuint8_array = np.array([0, 128, 255], dtype=np.uint8)float32_array = uint8_array.astype(np.float32) / 255.0print(float32_array)输入后果为: [0. 0.5019608 1. ]在这里,咱们首先创立一个 np.uint8 类型的数组 uint8_array,蕴含了三个元素:0、128 和 255。而后,咱们应用 astype 函数将其转换为 np.float32 类型的数组 float32_array。为了将数据归一化到 [0, 1] 的范畴内,咱们还须要将 float32_array 中的每个元素除以 255。

April 17, 2023 · 1 min · jiezi

关于numpy:对于numpy中的ndarray有关axis的理解

次要启发是起源这篇文章而后本人画了个图,加深了一下本人的印象,记录一下 首先了解np.ones((3,4,5))中(3,4,5)代表了啥,看代码我的了解是3示意深度为3,4示意高度为4,5示意宽度为5所以np.ones((3,4,5))大抵生成的3维数组是这样的接着看axis 如果是axis=0,那么他示意的立体就是(height,width)这个立体 如果是axis=1,那么他示意的立体就是(depth,width)这个立体 如果是axis=2,那么他示意的立体就是(deepth,height)这个立体

January 25, 2023 · 1 min · jiezi

关于numpy:居然用-Numpy-实现了一个深度学习框架

明天跟大家分享一个牛逼的开源我的项目,该我的项目只用Numpy就实现了一个深度学习框架。 它不是一个demo, 而是一个实实在在能利用的深度学习框架,它的语法与PyTorch统一,用它能够实现CNN、RNN、DNN等经典的神经网络。 该框架对正在学习深度学习的敌人十分敌对,因为它的代码量不到 2000 行,大家齐全能够通过浏览源码来深刻理解神经网络外部的细节。 如果大家读完源码本人也能做一个相似的深度学习框架,就更完满了。 1. 与 PyTorch 比照接下来,我用该框架搭建一个简略的神经网络,并与PyTorch比照。 咱们用这个神经网络来实现线性回归: 用上面的函数来生成训练样本 def synthetic_data(w, b, num_examples):     """生成y=w1*x1+w2*x2+b训练样本"""    X = np.random.normal(0, 1, (num_examples, len(w)))    y = np.dot(X, w) + b    y += np.random.normal(0, 0.01, y.shape)    return X, y.reshape((-1, 1))w = np.array([2, -3.4])b = 4.2features, labels = synthetic_data(w, b, 1000)这里咱们令w1=2、w2=-3.4、b=4.2,随机生成1000个训练样本,x1、x2寄存在features变量中,y寄存在labels变量中。 上面咱们要做的是将这些样本输出神经网络中,训练出参数w1、w2和b,咱们心愿模型训练进去的参数跟理论的w1、w2和b越靠近越好。 先用PyTorch来搭建神经网络,并训练模型。 from torch import nn, Tensorimport torch# 只有一个神经元,并且是线性神经元# 2代表有2个特色(x1、x2),1代表输入1个特色(y)net = nn.Linear(2, 1)print(f'初始w:{net.weight.data}')print(f'初始b:{net.bias.data}')# 用均方误差作为线性回归损失函数loss = nn.MSELoss()# 采纳梯度降落算法优化参数,lr是学习速率trainer = torch.optim.SGD(net.parameters(), lr=0.03)# 转 TensorX = Tensor(features)y = Tensor(labels)# 迭代次数num_epochs = 300for epoch in range(num_epochs):    l = loss(net(X), y)  # 计算损失    trainer.zero_grad()    l.backward()  # 反向流传,求导    trainer.step()  # 更新参数    l = loss(net(X), y) # 参数更新后,再次计算损失    print(f'epoch {epoch + 1}, loss {round(float(l.data), 8)}')print(f'模型训练后的w:{net.weight.data}')print(f'模型训练后的b:{net.bias.data}')这里咱们用的是最简略的神经网络,只有一个神经元。 代码也比较简单,每行都做了正文。 输入的后果也是合乎咱们的预期,输入的损失如下: epoch 1, loss 33.65092468epoch 2, loss 29.78330231epoch 3, loss 26.36030769...epoch 298, loss 0.0001022epoch 299, loss 0.0001022epoch 300, loss 0.0001022前几轮损失比拟大,等迭代300次后,损失曾经十分小了。再看训练进去的参数: 初始w:tensor([[0.5753, 0.6624]])初始b:tensor([-0.5713])...模型训练后的w:tensor([[ 1.9995, -3.4001]])模型训练后的b:tensor([4.1998])能够看到,经过训练后,模型的参数与设定的参数也是十分靠近的。 上面,咱们再用明天介绍的框架再来实现一遍。 from pydynet import nn, Tensorfrom pydynet.optimizer import SGDnet = nn.Linear(2, 1)print(f'初始w:{net.weight.data}')print(f'初始b:{net.bias.data}')loss = nn.MSELoss()trainer = SGD(net.parameters(), lr=0.03)X = Tensor(features)y = Tensor(labels)num_epochs = 300for epoch in range(num_epochs):    l = loss(net(X), y)  # 计算损失    trainer.zero_grad()    l.backward()  # 反向流传,求导    trainer.step()  # 更新参数    l = loss(net(X), y)  # 参数更新后,再次计算损失    print(f'epoch {epoch + 1}, loss {round(float(l.data), 8)}')    print(f'模型训练后的w:{net.weight.data}')print(f'模型训练后的b:{net.bias.data}')代码从pydynet目录引入的,能够看到,用法跟PyTorch简直是截然不同,输入参数如下: 初始w:[[-0.25983338] [-0.29252936]]初始b:[-0.65241649]...模型训练后的w:[[ 2.00030734] [-3.39951581]]模型训练后的b:[4.20060585]训练进去的后果也是合乎预期的。 2. 我的项目构造pydynet我的项目架构如下: 目前只有 5 个 Python源文件,不到 2000 行代码。 第一大节咱们只实现最简略的神经网络,其余经典的神经网络,也有源码,大家能够自行查阅 我的项目地址:https://github.com/Kaslanaria... 我十分喜爱这个我的项目,拜服这个我的项目的作者。如果你也正好在学习人工智能,强烈建议学习学习这个我的项目。 以上就是本次分享的所有内容,如果你感觉文章还不错,欢送关注公众号:Python编程学习圈,每日干货分享,发送“J”还可支付大量学习材料,内容笼罩Python电子书、教程、数据库编程、Django,爬虫,云计算等等。或是返回编程学习网,理解更多编程技术常识。

July 14, 2022 · 1 min · jiezi

关于numpy:学习神经网络minibatch

1.numpy的切片X[m,n],示意X的第m维中的第n段数据。也能够按切片写法:X[m:n,k:v],第一维从m到n-1,第二维取从k到v-1X[:,n],示意第一维的m全副取,第二维取第n段数据,如果是矩阵,就是取第n列。 X[:,list],第二维依照list外面的数字索引取 import numpy as npnp.random.seed(1)X = np.random.randn(5,3)print(X)X是5行3列矩阵,后果: [[ 1.62434536 -0.61175641 -0.52817175] [-1.07296862 0.86540763 -2.3015387 ] [ 1.74481176 -0.7612069 0.3190391 ] [-0.24937038 1.46210794 -2.06014071] [-0.3224172 -0.38405435 1.13376944]]随机失去一个列表: np.random.seed(1)permutation = list(np.random.permutation(3))print(permutation)permutation列表是:[0, 2, 1] 按X[:,list]形式来取数据,也就是第一维全副取,第二维依照list的索引来取: shuffed_X = X[:,permutation]print(shuffed_X)后果是: [[ 1.62434536 -0.52817175 -0.61175641] [-1.07296862 -2.3015387 0.86540763] [ 1.74481176 0.3190391 -0.7612069 ] [-0.24937038 -2.06014071 1.46210794] [-0.3224172 1.13376944 -0.38405435]]因为这里list其实是从0-2的,其维度与n一样,实际上就是随机地把列进行打乱。

April 20, 2022 · 1 min · jiezi

关于numpy:numpy-官网文章翻译2

老手根底欢送来到 NumPy 的世界NumPy 是一个Python 开源库,简直能够利用于所有的迷信和工程畛域。在Python 中,它是解决数字型数据的通用规范,也是迷信 Python 与PyData 生态系统的外围。从初学者到经验丰富的钻研人员,只有是从事新进的迷信和工业钻研畛域,都是NumPy用户。Pandas、SCIPy、Matplotlib、scikit-learn、scikit-image 以及其余须要数据迷信包都含有 numpy 的 API 接口。 NumPy 库包含多种数组和矩阵数据结构。提供了一种均一的 n-维数组对象 ndarray及多种相应无效的操作方法。NumPy 在数组构造上能够用于操作多种数学计算。同时也为 Python 提供了一种无效的数据结构,以确保数组和矩阵无效计算,并为高水平数学方法提供了大量能够操作数组和矩阵的库。 装置如果你曾经装置 Python 的话,依照以下办法装置 conda install numpypip install numpy如果没有装置 Python,能够应用 anaconda,它是最简略的办法,且具备以下劣势:你不须要放心别离装置 NumPy 或者其余的 用于数据分析的Python 包,如 pandas、Scikit-Learn 等,conda 都会解决好 引入 NumPyimport numpy as np“np”是 numpy 的缩写,在应用numpy 时更加易读。 Python 列表与 NumPy 数组区别NumPy 提供了多种创立数组和操作数组数组的办法。Python 列表是一个列表中能够蕴含不同的数据类型,而数组的所有元素必须是统一的。如果数组的数据类型不统一,那么计算效率会大大降低。 应用 NumPy 的理由比起列表,数组有以下劣势 构造更加严密运行更加迅速占用内存少:数组存储数据应用的内存更少,并提供了一个指定数据类型的机制,这样能够更加优化代码使用方便数组是什么数组是NumPy 库的外围数据结构。数组是由值组成的网格构造,蕴含原始数据的信息、如何定位元素以及如何解释元素。数组有一个元素网格,能够以多种形式索引数据。这些元素的数据类型都统一,称为dtype 。 检索数组的数据类型有:非负整数的元素、布尔值、数组和整数。 数组的 rank指的是其维度的数量;数组的 shape是一个形容了每个维度大小的整数元组。 能够应用 Python 列表的形式初始化数组,应用巢式列表能够初始化二维及更高维度的数组 a = np.array([1, 2, 3, 4, 5, 6])a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])咱们能够应用中括号[]拜访数组中的元素,留神索引从 0 开始。 ...

January 18, 2022 · 7 min · jiezi

关于numpy:numpy-官网文章翻译

官网地址 什么是 numpynumpy 是 Python 的一个科学计算包。提供了多种array对象、衍生对象(masked arrays 和 matrices)、及其对其日常疾速操作,包含数学、逻辑、形态操作、分类、抉择、I/O、离散傅里叶(discrete Fourier transforms)、根本线性代数、根本数据操作、随机墨迹等。numpy 包的外围是ndarray,他分装了n-维 array 对象(每个维度的数据类型统一),这使得各种操作都在编译好的代码中执行,从而进步了性能。 NumPyarray对象 与 Python 规范序列区别: NumPy 对象在创立时有一个固定的大小,而 Python 的 list 没有。扭转 ndarray 的大小会删除原来对象,创立一个新的对象NumPy所有数据类型是统一的,这样在内存中占用的大小才是统一的。例外:能够有对象数组(Python,包含 NumPy),容许不同大小元素的数组。NumPy 对象更容易对于大量数据进行高级数学和其余类型操作。相较于 Python 内置序列,NumPy 操作执行效率更高,代码更少。越来越多的迷信和数学 Python 包会应用 NumPy 包,只管它们反对 Python 内置序列,但在操作之前都会转换成 NumPy 对象。换言之,要想无效的应用当初的迷信\数学 Python 包,只理解 Python 内置序列是不够的,咱们也要理解 NumPy 对象的应用。科学计算的要害就是序列大小和速度。举个简略例子,在一个一维的序列中,每个元素要与另一个长度雷同的序列相应的元素做乘积,咱们能够迭代每个元素。 c = []for i in range(len(a)): c.append(a[i]*b[i])这个过程会输入正确答案,但如果列表 a 和 b 每个元素都是几百万,那咱们就会为 Python 低效的循环付出代价。c 语言能够更快的实现雷同工作(咱们假如不去做变量申明、初始化和内存调配): for(i = 0; i < rows; i++):{ c[i] = a[i]*b[i]}这解决了解释Python代码和操作Python对象所波及的所有开销,但就义了Python编码的益处。此外,随着数据维度减少,工作量也减少,如在 2 维数组中,c 语言编码为 ...

January 14, 2022 · 4 min · jiezi

关于numpy:18-个-实用的Numpy-代码片段总结

Numpy 长期以来始终是 Python 开发人员进行数组操作的通用抉择,它是基于C语言构建的这使得它成为执行数组操作的疾速和牢靠的抉择,并且它曾经成为机器学习和数据迷信必备的根底库。 在本文中,我整顿了一些 NumPy 代码的片段,这些代码片段都是在日常开发中常常用到的。 1、创立数组 import numpy as npnew_array = np.array([1,2,3])print(new_array)# Output[1 2 3]2、获取 Numpy 数组的形态、维度和大小 # shapeprint(new_array.shape)# dimensionsprint(new_array.ndim)# sizeprint(new_array.size)# Output(3,)133、查看Numpy数组中元素的类型 array = np.arange(0,10,1)print(array.dtype)# Outputint644、获取数组中每个元素的占用字节大小 array = np.array([1,2])print(array.itemsize)# Output85、创立时指定数组的类型 array = np.array([[1,2], [3,4]], dtype=complex)array# Outputarray([[1.+0.j, 2.+0.j], [3.+0.j, 4.+0.j]])6、应用占位符创立数组 # 全零数组array = np.zeros((3,4))print(array)print("---")# 全1数组array = np.ones((1,2))print(array)print("---")# shape (2,3)的空数组,随机产生数据array = np.empty((2,3))print(array)print("---")# Output[[0. 0. 0. 0.] [0. 0. 0. 0.] [0. 0. 0. 0.]]---[[1. 1.]]---[[4.67280967e-310 0.00000000e+000 0.00000000e+000] [0.00000000e+000 0.00000000e+000 0.00000000e+000]]---7、创立序列 ...

December 15, 2021 · 3 min · jiezi

关于numpy:NumPy之ndarray多维数组操作

简介NumPy一个十分重要的作用就是能够进行多维数组的操作,多维数组对象也叫做ndarray。咱们能够在ndarray的根底上进行一系列简单的数学运算。 本文将会介绍一些根本常见的ndarray操作,大家能够在数据分析中应用。 创立ndarray创立ndarray有很多种办法,咱们能够应用np.random来随机生成数据: import numpy as np# Generate some random datadata = np.random.randn(2, 3)dataarray([[ 0.0929, 0.2817, 0.769 ], [ 1.2464, 1.0072, -1.2962]])除了随机创立之外,还能够从list中创立: data1 = [6, 7.5, 8, 0, 1]arr1 = np.array(data1)array([6. , 7.5, 8. , 0. , 1. ])从list中创立多维数组: data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]arr2 = np.array(data2)array([[1, 2, 3, 4], [5, 6, 7, 8]])应用np.zeros创立初始值为0的数组: np.zeros(10)array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])创立2维数组: np.zeros((3, 6))array([[0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0.]])应用empty创立3维数组: ...

May 19, 2021 · 5 min · jiezi

关于numpy:NumPy之理解广播

简介播送形容的是NumPy如何计算不同形态的数组之间的运算。如果是较大的矩阵和较小的矩阵进行运算的话,较小的矩阵就会被播送,从而保障运算的正确进行。 本文将会以具体的例子具体解说NumPy中播送的应用。 根底播送失常状况下,两个数组须要进行运算,那么每个数组的对象都须要有一个绝对应的值进行计算才能够。比方上面的例子: a = np.array([1.0, 2.0, 3.0])b = np.array([2.0, 2.0, 2.0])a * barray([ 2., 4., 6.])然而如果应用Numpy的播送个性,那么就不必须元素的个数精确对应。 比方,咱们能够讲一个数组乘以常量: a = np.array([1.0, 2.0, 3.0])>>> b = 2.0>>> a * barray([ 2., 4., 6.])上面的例子和下面的例子是等价的,Numpy会主动将b进行扩大。 NumPy足够聪慧,能够应用原始标量值而无需理论制作正本,从而使播送操作尽可能地节俭内存并进步计算效率。 第二个示例中的代码比第一个示例中的代码更无效,因为播送在乘法过程中挪动的内存更少(b是标量而不是数组)。 播送规定如果两个数组操作,NumPy会对两个数组的对象进行比拟,从最初一个维度开始,如果两个数组的维度满足上面的两个条件,咱们就认为这两个数组是兼容的,能够进行运算: 维度中的元素个数是雷同的其中一个维数是1如果下面的两个条件不满足的话,就会抛出异样: ValueError: operands could not be broadcast together。 维度中的元素个数是雷同的,并不意味着要求两个数组具备雷同的维度个数。 比方示意色彩的256x256x3 数组,能够和一个一维的3个元素的数组相乘: Image (3d array): 256 x 256 x 3Scale (1d array): 3Result (3d array): 256 x 256 x 3相乘的时候,维度中元素个数是1的会被拉伸到和另外一个维度中的元素个数统一: A (4d array): 8 x 1 x 6 x 1B (3d array): 7 x 1 x 5Result (4d array): 8 x 7 x 6 x 5下面的例子中,第二维的1被拉伸到7,第三维的1被拉伸到6,第四维的1被拉伸到5。 ...

May 12, 2021 · 2 min · jiezi

关于numpy:NumPy之结构化数组详解

简介一般的数组就是数组中寄存了同一类型的对象。而结构化数组是指数组中寄存不同对象的格局。 明天咱们来具体探讨一下NumPy中的结构化数组。 结构化数组中的字段field因为结构化数组中蕴含了不同类型的对象,所以每一个对象类型都被称为一个field。 每个field都有3局部,别离是:string类型的name,任何无效dtype类型的type,还有一个可选的title。 看一个应用filed构建dtype的例子: In [165]: np.dtype([('name', 'U10'), ('age', 'i4'), ('weight', 'f4')])Out[165]: dtype([('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])咱们能够应用下面的dtype类型来构建一个新的数组: In [166]: x = np.array([('Rex', 9, 81.0), ('Fido', 3, 27.0)], ...: dtype=[('name', 'U10'), ('age', 'i4'), ('weight', 'f4')]) ...:In [167]: xOut[167]:array([('Rex', 9, 81.), ('Fido', 3, 27.)], dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])x是一个1维数组,每个元素都蕴含三个字段,name,age和weight。并且别离指定了他们的数据类型。 能够通过index来拜访一行数据: In [168]: x[1]Out[168]: ('Fido', 3, 27.)也能够通过name来拜访一列数据 : In [170]: x['name']Out[170]: array(['Rex', 'Fido'], dtype='<U10')还能够给所有的列对立赋值: In [171]: x['age']Out[171]: array([9, 3], dtype=int32)In [172]: x['age'] = 10In [173]: xOut[173]:array([('Rex', 10, 81.), ('Fido', 10, 27.)], dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])结构化数据类型下面的例子让咱们对结构化数据类型有了一个根本的意识。结构化数据类型就是一系列的filed的汇合。 ...

May 6, 2021 · 4 min · jiezi

关于数据科学:ApacheCN-数据科学译文集-20210313-更新

新增了五个教程: Python 和 Jupyter 机器学习入门 零、前言一、Jupyter 基础知识二、数据清理和高级机器学习三、Web 爬取和交互式可视化Python 数据迷信和机器学习实际指南 零、前言一、入门二、统计和概率回顾和 Python 实际三、Matplotlib 和高级概率概念四、预测模型五、Python 机器学习六、举荐零碎七、更多数据挖掘和机器学习技术八、解决实在数据九、Apache Spark-大数据机器学习十、测试与实验设计精通 Python 数据迷信 零、前言一、原始数据入门二、推断统计三、海底捞针四、通过高级可视化感知数据五、发现机器学习六、应用线性回归执行预测七、预计事件的可能性八、应用协同过滤生成倡议九、应用集成模型扩大边界十、通过 K 均值聚类利用细分十一、通过文本开掘剖析非结构化数据十二、在大数据世界中利用 PythonPython 数据迷信本质论 零、前言一、第一步二、数据整顿三、数据管道四、机器学习五、可视化,见解和后果六、社交网络分析七、超过根底的深度学习八、大数据和 Spark九、增强您的 Python 根底数据迷信思维 零、前言一、开发人员对数据迷信的认识二、应用 Jupyter 笔记本和 PixieDust 的大规模数据迷信三、PixieApp 深刻理解四、应用 PixieGateway 服务器将 PixieApp 部署到 Web五、最佳实际和高级 PixieDust 概念六、TensorFlow 图像识别七、大数据和 Twitter 情感剖析八、金融工夫序列剖析和预测九、应用图的美国国内航班数据分析十、最终思维十一、附录 A:PixieApp 疾速参考下载Dockerdocker pull apachecn0/apachecn-cv-zhdocker run -tid -p <port>:80 apachecn0/apachecn-cv-zh# 拜访 http://localhost:{port} PYPIpip install apachecn-cv-zhapachecn-cv-zh <port># 拜访 http://localhost:{port} NPMnpm install -g apachecn-cv-zhapachecn-cv-zh <port># 拜访 http://localhost:{port} 奉献指南本我的项目须要校对,欢送大家提交 Pull Request。 ...

March 13, 2021 · 1 min · jiezi

关于numpy:ApacheCN-数据科学译文集-20208

协定:CC BY-NC-SA 4.0不要放心本人的形象,只关怀如何实现目标。——《准则》,生存准则 2.3.c 在线浏览ApacheCN 面试求职交换群 724187166ApacheCN 学习资源目录TutorialsPoint NumPy 教程NumPy 秘籍中文第二版 零、前言一、应用 IPython二、高级索引和数组概念三、把握罕用函数四、将 NumPy 与世界的其余中央连贯五、音频和图像处理六、非凡数组和通用函数七、性能剖析和调试八、质量保证九、应用 Cython 减速代码十、Scikits 的乐趣十一、最新最强的 NumPy十二、应用 NumPy 进行探索性和预测性数据分析NumPy 初学者指南中文第三版 零、前言一、NumPy 疾速入门二、从 NumPy 基本原理开始三、相熟罕用函数四、为您带来便当的便当函数五、应用矩阵和 ufunc六、深刻摸索 NumPy 模块七、理解非凡例程八、通过测试确保品质九、matplotlib 绘图十、当 NumPy 不够用时 - SciPy 及更多十一、玩转 Pygame附录 A:小测验答案附录 B:其余在线资源附录 C:NumPy 函数的参考NumPy 基础知识 零、前言一、NumPy 简介二、NumPy ndarray对象三、应用 NumPy 数组四、NumPy 外围和子模块五、NumPy 中的线性代数六、NumPy 中的傅立叶剖析七、构建和散发 NumPy 代码八、应用 Cython 减速 NumPy九、NumPy C-API 简介十、扩大浏览精通 NumPy 数值剖析 零、前言一、应用 NumPy 数组二、NumPy 线性代数三、应用 NumPy 统计函数对波士顿住房数据进行探索性数据分析四、应用线性回归预测房价五、应用 NumPy 对零售分销商的客户进行聚类六、NumPy,SciPy,Pandas 和 Scikit-Learn七、高级 NumPy八、高性能数值计算库概述九、性能基准NumPy 数组学习手册 ...

August 2, 2020 · 1 min · jiezi

关于numpy:ApacheCN-数据科学译文集-20208

协定:CC BY-NC-SA 4.0不要放心本人的形象,只关怀如何实现目标。——《准则》,生存准则 2.3.c 在线浏览ApacheCN 面试求职交换群 724187166ApacheCN 学习资源目录TutorialsPoint NumPy 教程NumPy 秘籍中文第二版 零、前言一、应用 IPython二、高级索引和数组概念三、把握罕用函数四、将 NumPy 与世界的其余中央连贯五、音频和图像处理六、非凡数组和通用函数七、性能剖析和调试八、质量保证九、应用 Cython 减速代码十、Scikits 的乐趣十一、最新最强的 NumPy十二、应用 NumPy 进行探索性和预测性数据分析NumPy 初学者指南中文第三版 零、前言一、NumPy 疾速入门二、从 NumPy 基本原理开始三、相熟罕用函数四、为您带来便当的便当函数五、应用矩阵和 ufunc六、深刻摸索 NumPy 模块七、理解非凡例程八、通过测试确保品质九、matplotlib 绘图十、当 NumPy 不够用时 - SciPy 及更多十一、玩转 Pygame附录 A:小测验答案附录 B:其余在线资源附录 C:NumPy 函数的参考NumPy 基础知识 零、前言一、NumPy 简介二、NumPy ndarray对象三、应用 NumPy 数组四、NumPy 外围和子模块五、NumPy 中的线性代数六、NumPy 中的傅立叶剖析七、构建和散发 NumPy 代码八、应用 Cython 减速 NumPy九、NumPy C-API 简介十、扩大浏览精通 NumPy 数值剖析 零、前言一、应用 NumPy 数组二、NumPy 线性代数三、应用 NumPy 统计函数对波士顿住房数据进行探索性数据分析四、应用线性回归预测房价五、应用 NumPy 对零售分销商的客户进行聚类六、NumPy,SciPy,Pandas 和 Scikit-Learn七、高级 NumPy八、高性能数值计算库概述九、性能基准NumPy 数组学习手册 ...

August 2, 2020 · 1 min · jiezi

关于numpy:NumPy-数组学习手册翻译完成

原文:Learning NumPy Array协定:CC BY-NC-SA 4.0 欢送任何人参加和欠缺:一个人能够走的很快,然而一群人却能够走的更远。 在线浏览ApacheCN 面试求职交换群 724187166ApacheCN 学习资源目录NumPy 数组学习手册零、前言一、NumPy 入门二、NumPy 根底三、应用 NumPy 的根本数据分析四、应用 NumPy 的简略预测性剖析五、信号处理技术六、性能剖析,调试和测试七、Python 迷信生态系统奉献指南本我的项目须要校对,欢送大家提交 Pull Request。 请您怯懦地去翻译和改良翻译。尽管咱们谋求卓越,但咱们并不要求您做到美中不足,因而请不要放心因为翻译上犯错——在大部分状况下,咱们的服务器曾经记录所有的翻译,因而您不用放心会因为您的失误受到无法挽回的毁坏。(改编自维基百科)联系方式负责人飞龙: 562826179其余在咱们的 apachecn/apachecn-ds-zh github 上提 issue.发邮件到 Email: apachecn@163.com.在咱们的 组织学习交换群 中分割群主/管理员即可.资助咱们通过平台自带的打赏性能,或点击这里。

July 26, 2020 · 1 min · jiezi

关于numpy:NumPy-基础知识翻译完成

原文:Numpy Essentials协定:CC BY-NC-SA 4.0 欢送任何人参加和欠缺:一个人能够走的很快,然而一群人却能够走的更远。 在线浏览ApacheCN 面试求职交换群 724187166ApacheCN 学习资源目录NumPy 基础知识零、前言一、NumPy 简介二、NumPy ndarray对象三、应用 NumPy 数组四、NumPy 外围和子模块五、NumPy 中的线性代数六、NumPy 中的傅立叶剖析七、构建和散发 NumPy 代码八、应用 Cython 减速 NumPy九、NumPy C-API 简介十、扩大浏览奉献指南本我的项目须要校对,欢送大家提交 Pull Request。 请您怯懦地去翻译和改良翻译。尽管咱们谋求卓越,但咱们并不要求您做到美中不足,因而请不要放心因为翻译上犯错——在大部分状况下,咱们的服务器曾经记录所有的翻译,因而您不用放心会因为您的失误受到无法挽回的毁坏。(改编自维基百科)联系方式负责人飞龙: 562826179其余在咱们的 apachecn/apachecn-ds-zh github 上提 issue.发邮件到 Email: apachecn@163.com.在咱们的 组织学习交换群 中分割群主/管理员即可.资助咱们通过平台自带的打赏性能,或点击这里。

July 24, 2020 · 1 min · jiezi

关于numpy:NumPy-基础知识翻译完成

原文:Numpy Essentials协定:CC BY-NC-SA 4.0 欢送任何人参加和欠缺:一个人能够走的很快,然而一群人却能够走的更远。 在线浏览ApacheCN 面试求职交换群 724187166ApacheCN 学习资源目录NumPy 基础知识零、前言一、NumPy 简介二、NumPy ndarray对象三、应用 NumPy 数组四、NumPy 外围和子模块五、NumPy 中的线性代数六、NumPy 中的傅立叶剖析七、构建和散发 NumPy 代码八、应用 Cython 减速 NumPy九、NumPy C-API 简介十、扩大浏览奉献指南本我的项目须要校对,欢送大家提交 Pull Request。 请您怯懦地去翻译和改良翻译。尽管咱们谋求卓越,但咱们并不要求您做到美中不足,因而请不要放心因为翻译上犯错——在大部分状况下,咱们的服务器曾经记录所有的翻译,因而您不用放心会因为您的失误受到无法挽回的毁坏。(改编自维基百科)联系方式负责人飞龙: 562826179其余在咱们的 apachecn/apachecn-ds-zh github 上提 issue.发邮件到 Email: apachecn@163.com.在咱们的 组织学习交换群 中分割群主/管理员即可.资助咱们通过平台自带的打赏性能,或点击这里。

July 24, 2020 · 1 min · jiezi

Numpy应用案例

Numpy应用案例注:__使用numpy库来对图像进行处理。__这里我们使用matplotlib.pyplot的相关方法来辅助。 处理图像的时候,颜色都是使用RGB三个通道进行叠加而形成的一个颜色 _R:__红色通道__G:__绿色__B: 蓝色_ 可以使用三维的数组来表示一张图片 最高维度0:__图片的高度 次高维1:__图片的宽度 最低维2:__RGB三个元素 In [2]: import numpy as np import matplotlib.pyplot as plt 图像读取与显示plt.imread:读取图像,返回图像的数组(三维数组)。plt.imshow:显示图像。plt.imsave:保存图像。说明: imread方法默认只能处理png格式的图像,如果需要处理其他格式的图像,需要安装pillow库。In [62]: a=plt.imread("1.jpg") # 将图片信息读取成数组信息 # 返回的信息是一个三维的数组 # 最高维度:一共有332个元素 # 次高维:一共有500个元素 # 最低维:每个像素点的颜色信r g b a #已知数组信息,使用imshow读取成图片 plt.imshow(a) # 将数组信息存储成图片 plt.imsave("c:/numpy.jpg",a) # 利用已学过的知识显示数组a的形状 print(a.shape) (332, 500, 3) 显示纯色图像显示白色图像显示黑色图像显示指定颜色图像In [23]: # (1)如何在ndarray数组中存储一张图片。 # 三维:最高维:高 # 次高维:宽 # 最低维:颜色 # 颜色的存储: # 在numpy中可以有两种形式: # 3 rgb颜色值越大,图片就越亮 一种是无符号 uint8 0-255float类型 float 0-1# x=np.ones(shape=(100,200,3))#白色图像,rgb[1,1,1] # x=np.zeros(shape=(100,200,3))#黑色色图像,rgb[0,0,0] # x=np.full(shape=(100,200,3),fill_value=255)#rgb[255,255,255] # plt.imshow(x) ...

October 15, 2019 · 2 min · jiezi

Python-的整数与-Numpy-的数据溢出

某位 A 同学发了我一张截图,问为何结果中出现了负数? 看了图,我第一感觉就是数据溢出了。数据超出能表示的最大值,就会出现奇奇怪怪的结果。 然后,他继续发了张图,内容是 print(100000*208378),就是直接打印上图的 E[0]*G[0],结果是 20837800000,这是个正确的结果。 所以新的问题是:如果说上图的数据溢出了,为何直接相乘的数却没有溢出? 由于我一直忽视数据的表示规则(整型的上限是多少?),而且对 Numpy 了解不多,还错看了图中结果,误以为每一个数据都是错误的,所以就解答不出来。 最后,经过学习群里的一番讨论,我才终于明白是怎么回事,所以本文把相关知识点做个梳理。 在正式开始之前,先总结一下上图会引出的话题: Python 3 中整数的上限是多少?Python 2 呢?Numpy 中整数的上限是多少?出现整数溢出该怎么办?关于第一个问题,先看看 Python 2,它有两种整数: 一种是短整数,也即常说的整数,用 int 表示,有个内置函数 int()。其大小有限,可通过sys.maxint() 查看(取决于平台是 32 位还是 64 位)一种是长整数,即大小无限的整数,用 long 表示,有个内置函数 long()。写法上是在数字后面加大写字母 L 或小写的 l,如 1000L当一个整数超出短整数范围时,它会自动采用长整数表示。举例,打印 2**100 ,结果会在末尾加字母 L 表示它是长整数。 但是到了 Python 3,情况就不同了:它仅有一种内置的整数,表示为 int,形式上是 Python 2 的短整数,但实际上它能表示的范围无限,行为上更像是长整数。无论多大的数,结尾都不需要字母 L 来作区分。 也就是说,Python 3 整合了两种整数表示法,用户不再需要自行区分,全交给底层按需处理。 理论上,Python 3 中的整数没有上限(只要不超出内存空间)。这就解释了前文中直接打印两数相乘,为什么结果会正确了。 PEP-237(Unifying Long Integers and Integers)中对这个转变作了说明。它解释这样做的 目的: 这会给新的 Python 程序员(无论他们是否是编程新手)减少一项上手前要学的功课。Python 在语言运用层屏蔽了很多琐碎的活,比如内存分配,所以,我们在使用字符串、列表或字典等对象时,根本不用操心。整数类型的转变,也是出于这样的便利目的。(坏处是牺牲了一些效率,在此就不谈了) ...

September 10, 2019 · 1 min · jiezi

NumPy-数组大全

NumPy 是一个Python 库,用于 Python 编程中的科学计算。在本教程中,你将学习如何在 NumPy 数组上以多种方式添加、删除、排序和操作元素。 NumPy 提供了一个多维数组对象和其他派生数组,例如掩码数组和掩码多维数组。 为什么要用 NumPyNumPy 提供了一个 ndarray 对象,可以使用它来对任何维度的数组进行操作。 ndarray 代表 N 维数组,其中 N 是任意数字。这意味着 NumPy 数组可以是任何维度的。 与 Python 的 List 相比,NumPy 具有许多优势。我们可以在 NumPy 阵列上执行高性能操作,例如: 对数组成员进行排序数学和逻辑运算输入/输出功能统计和线性代数运算安装 NumPy要安装NumPy,你的电脑上要先有 Python 和 Pip。 在终端中运行以下命令: pip install numpy然后你就可以在脚本中导入 NumPy 了,如下所示: import numpy添加数组元素可以用 NumPy 模块的 append() 方法向 NumPy 数组中添加元素。 append() 的语法如下: numpy.append(array, value, axis)value 会被追加到在数组的末尾,并返回一个包含所有元素的 ndarray。 参数 axis 是一个可选的整数,用于定义数组的显示方式。如果没有指定,则数组结构将展平,稍后会演示用法。 以下示例,其中首先声明数组,然后用 append 方法向数组添加更多的值: import numpya = numpy.array([1, 2, 3])newArray = numpy.append (a, [10, 11, 12])print(newArray)# 输出:[ 1 2 3 10 11 12]添加一列也可以用NumPy 的 append() 方法插入一列。 ...

April 24, 2019 · 4 min · jiezi

NumPy-基本切片和索引

https://docs.scipy.org/doc/nu... 索引ndarrays可以使用标准Python x[obj]语法对其进行索引 ,其中x是数组,obj是选择方式。有三种可用的索引:字段访问,基本切片,高级索引。究竟是哪一个取决于obj。 注意在Python中,x[(exp1, exp2, ..., expN)]相当于 x[exp1, exp2, ..., expN]; 后者只是前者的语法糖。基本切片和索引基本切片将 Python 的切片基本概念扩展到 N 维。当obj是一个slice对象(由括号内的start:stop:step符号构造)、整数或切片对象和整数的元组时,会发生基本切片。也包括省略号(三个点)和newaxis对象。 从版本1.15.0开始不推荐使用:为了保持向后兼容Numeric中的常见用法,如果选择对象是包含 slice 对象、省略号,或 newaxis 对象的任何非 nararray 和非元组序列(例如 list),则也会启动基本切片,但不适用于整数数组或其他嵌入序列。 使用 N 个整数进行索引的最简单情况返回表示相应项的数组标量。正如在 Python 中,所有下标是从零开始:对我个索引你,取值范围为 $$ 0 \le n_i < d_i $$ 其中d_i是 我的阵列的形状的个元素。负指数被解释为从数组的末尾开始计数(即,如果 n_i <0,则意味着n_i + d_i)。 基本切片生成的所有数组始终 是原始数组的视图。 序列切片的标准规则适用于基于每维的基本切片(包括使用步骤索引)。要记住的一些有用的概念包括: 基本切片语法是i:j:k其中我是起始索引, j是停止索引,并且ķ是步骤 $$ k \neq 0 $$ 。这将选择米元件(在对应的尺寸)与索引值我,i,i+k,...,1 +(m - 1)k, 其中 $$ m = q +(r \ neq0)$$和 q 和 r 是通过j-i 除 k 所获得的商和余数: $$ j - i = qk + r $$,因此 $$ i +(m - 1)k <j $$。 ...

April 24, 2019 · 3 min · jiezi

Pandas之旅(七) 谁说pandas慢

Pandas 加速大家好,今天我们来看有关pandas加速的小技巧,不知道大家在刚刚接触pandas的时候有没有听过如下的说法pandas太慢了,运行要等半天**其实我想说的是,慢不是pandas的错,大家要知道pandas本身是在Numpy上建立起来的包,在很多情况下是支持向量化运算的,而且还有C的底层设计,所以我今天主要想从几个方面和大家分享一下pandas加速的小技巧,与往常一样,文章分成四部分,本文结构如下:使用datetime类型来处理和时间序列有关的数据批量计算的技巧通过HDFStore存储数据节省时间源码,相关数据及GitHub地址现在就让我们开始吧1. 使用datetime类型来处理和时间序列有关的数据首先这里我们使用的数据源是一个电力消耗情况的数据(energy_cost.csv),非常贴近生活而且也是和时间息息相关的,用来做测试在合适不过了,这个csv文件大家可以在第四部分找到下载的地方哈import os# 这两行仅仅是切换路径,方便我上传Github,大家不用理会,只要确认csv文件和py文件再一起就行啦os.chdir(“F:\Python教程\segmentfault\pandas_share\Pandas之旅_07 谁说pandas慢”)现在让我们看看数据大概长什么样子import numpy as npimport pandas as pdf"Using {pd.name},{pd.version}"‘Using pandas,0.23.0’df = pd.read_csv(’energy_cost.csv’,sep=’,’)df.head() date_time energy_kwh 0 2001/1/13 0:00 0.586 1 2001/1/13 1:00 0.580 2 2001/1/13 2:00 0.572 3 2001/1/13 3:00 0.596 4 2001/1/13 4:00 0.592 现在我们看到初始数据的样子了,主要有date_time和energy_kwh这两列,来表示时间和消耗的电力,比较好理解,下面让我们来看一下数据类型df.dtypes>>> date_time object energy_kwh float64 dtype: objecttype(df.iat[0,0])>>> str这里有个小问题,Pandas和NumPy有dtypes(数据类型)的概念。如果未指定参数,则date_time这一列的数据类型默认object,所以为了之后运算方便,我们可以把str类型的这一列转化为timestamp类型:df[‘date_time’] = pd.to_datetime(df[‘date_time’])df.dtypes>>> date_time datetime64[ns] energy_kwh float64 dtype: object先在大家可以发现我们通过用pd.to_datetime这个方法已经成功的把date_time这一列转化为了datetime64类型df.head() date_time energy_kwh 0 2001-01-13 00:00:00 0.586 1 2001-01-13 01:00:00 0.580 2 2001-01-13 02:00:00 0.572 3 2001-01-13 03:00:00 0.596 4 2001-01-13 04:00:00 0.592 现在再来看数据, 发现已经和刚才不同了,我们还可以通过指定format参数实现一样的效果,速度上也会快一些%%timeit -n 10def convert_with_format(df, column_name): return pd.to_datetime(df[column_name],format=’%Y/%m/%d %H:%M’)df[‘date_time’]=convert_with_format(df, ‘date_time’)>>>722 µs ± 334 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)有关具体的日期自定义相关方法,大家点击这里查看2. 批量计算的技巧首先,我们假设根据用电的时间段不同,电费价目表如下:Typecents/kwhperiodePeak2817:00 to 24:00Shoulder207:00 to 17:00Off-Peak120:00 to 7:00假设我们想要计算出电费,我们可以先写出一个根据时间动态计算电费的方法“apply_tariff“def apply_tariff(kwh, hour): “““Calculates cost of electricity for given hour.””” if 0 <= hour < 7: rate = 12 elif 7 <= hour < 17: rate = 20 elif 17 <= hour < 24: rate = 28 else: raise ValueError(f’Invalid hour: {hour}’) return rate * kwh好啦,现在我们想要在数据中新增一列 ‘cost_cents’ 来表示总价钱,我们有很多选择,首先能想到的方法便是iterrows(),它可以让我们循环遍历Dataframe的每一行,根据条件计算并赋值给新增的‘cost_cents’列iterrows()首先我们能做的是循环遍历流程,让我们先用.iterrows()替代上面的方法来试试:%%timeit -n 10def apply_tariff_iterrows(df): energy_cost_list = [] for index, row in df.iterrows(): # Get electricity used and hour of day energy_used = row[’energy_kwh’] hour = row[‘date_time’].hour # Append cost list energy_cost = apply_tariff(energy_used, hour) energy_cost_list.append(energy_cost) df[‘cost_cents’] = energy_cost_listapply_tariff_iterrows(df)983 ms ± 65.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)我们为了测试方便,所有的方法都会循环10次来比较耗时,这里很明显我们有很大的改进空间,下面我们用apply方法来优化apply()%%timeit -n 10def apply_tariff_withapply(df): df[‘cost_cents’] = df.apply( lambda row: apply_tariff( kwh=row[’energy_kwh’], hour=row[‘date_time’].hour), axis=1)apply_tariff_withapply(df)247 ms ± 24.3 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)这回速度得到了很大的提升,但是显然我们还没有get到pandas加速的精髓:矢量化操作。下面让我们开始提速isin()假设我们现在的电价是定值,不根据用电时间段来改变,那么pandas中最快的方法那就是采用(df[‘cost_cents’] = df[’energy_kwh’] * price),这就是一个简单的矢量化操作示范。它基本是在Pandas中运行最快的方式。目前的问题是我们的价格是动态的,那么如何将条件判断添加到Pandas中的矢量化运算中呢?答案就是我们根据条件选择和分组DataFrame,然后对每个选定的组应用矢量化操作:#先让我们把时间序列作为索引df.set_index(‘date_time’, inplace=True)%%timeit -n 10def apply_tariff_isin(df): # Define hour range Boolean arrays peak_hours = df.index.hour.isin(range(17, 24)) shoulder_hours = df.index.hour.isin(range(7, 17)) off_peak_hours = df.index.hour.isin(range(0, 7)) # Apply tariffs to hour ranges df.loc[peak_hours, ‘cost_cents’] = df.loc[peak_hours, ’energy_kwh’] * 28 df.loc[shoulder_hours,‘cost_cents’] = df.loc[shoulder_hours, ’energy_kwh’] * 20 df.loc[off_peak_hours,‘cost_cents’] = df.loc[off_peak_hours, ’energy_kwh’] * 12apply_tariff_isin(df)5.7 ms ± 871 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)这回我们发现速度是真正起飞了,首先我们根据用电的三个时段把df进行分三组,再依次进行三次矢量化操作,大家可以发现最后减少了很多时间,原理很简单:在运行的时候,.isin()方法返回一个布尔值数组,如下所示:[False, False, False, …, True, True, True]接下来布尔数组传递给DataFrame的.loc索引器时,我们获得一个仅包含与3个用电时段匹配DataFrame切片。然后简单的进行乘法操作就行了,这样做的好处是我们已经不需要刚才提过的apply方法了,因为不在存在遍历所有行的问题我们可以做的更好吗?通过观察可以发现,在apply_tariff_isin()中,我们仍然在通过调用df.loc和df.index.hour.isin()来进行一些“手动工作”。如果想要进一步提速,我们可以使用cut方法%%timeit -n 10def apply_tariff_cut(df): cents_per_kwh = pd.cut(x=df.index.hour, bins=[0, 7, 17, 24], include_lowest=True, labels=[12, 20, 28]).astype(int) df[‘cost_cents’] = cents_per_kwh * df[’energy_kwh’]140 ns ± 29.9 ns per loop (mean ± std. dev. of 7 runs, 10 loops each)效果依然锋利,速度上有了成倍的提升不要忘了用Numpy众所周知,Pandas是在Numpy上建立起来的,所以在Numpy中当然有类似cut的方法可以实现分组,从速度上来讲差不太多%%timeit -n 10def apply_tariff_digitize(df): prices = np.array([12, 20, 28]) bins = np.digitize(df.index.hour.values, bins=[7, 17, 24]) df[‘cost_cents’] = prices[bins] * df[’energy_kwh’].values54.9 ns ± 19.3 ns per loop (mean ± std. dev. of 7 runs, 10 loops each)正常情况下,以上的加速方法是能满足日常需要的,如果有特殊的需求,大家可以上网看看有没有相关的第三方加速包3. 通过HDFStore存储数据节省时间这里主要想强调的是节省预处理的时间,假设我们辛辛苦苦搭建了一些模型,但是每次运行之前都要进行一些预处理,比如类型转换,用时间序列做索引等,如果不用HDFStore的话每次都会花去不少时间,这里Python提供了一种解决方案,可以把经过预处理的数据存储为HDF5格式,方便我们下次运行时直接调用。下面就让我们把本篇文章的df通过HDF5来存储一下:# Create storage object with filename processed_datadata_store = pd.HDFStore(‘processed_data.h5’)# Put DataFrame into the object setting the key as ‘preprocessed_df’data_store[‘preprocessed_df’] = dfdata_store.close()现在我们可以关机下班了,当明天接着上班后,通过key(“preprocessed_df”)就可以直接使用经过预处理的数据了# Access data storedata_store = pd.HDFStore(‘processed_data.h5’)# Retrieve data using keypreprocessed_df = data_store[‘preprocessed_df’]data_store.close()preprocessed_df.head() energy_kwh cost_cents date_time 2001-01-13 00:00:00 0.586 7.032 2001-01-13 01:00:00 0.580 6.960 2001-01-13 02:00:00 0.572 6.864 2001-01-13 03:00:00 0.596 7.152 2001-01-13 04:00:00 0.592 7.104 如上图所示,现在我们可以发现date_time已经是处理为index了4. 源码,相关数据及GitHub地址这一期为大家分享了一些pandas加速的实用技巧,希望可以帮到各位小伙伴,当然,类似的技巧还有很多,但是核心思想应该一直围绕矢量化操作上,毕竟是基于Numpy上建立的包,如果大家有更好的办法,希望可以在我的文章底下留言哈我把这一期的ipynb文件,py文件以及我们用到的energy_cost.csv放到了Github上,大家可以点击下面的链接来下载:Github仓库地址: https://github.com/yaozeliang/pandas_share希望大家能够继续支持我,这一篇文章已经是Pandas系列的最后一篇了,虽然一共只写了7篇文章,但是我认为从实用性上来讲并没有太逊色于收费课程(除了少了很多漂亮的ppt),接下来我会再接再厉,分享一下我对R (ggplot2)或者matplotlib的学习经验!!Pandas之旅到此结束。撒花 ...

April 5, 2019 · 3 min · jiezi

Pandas之旅(六): 字符串实用方法汇总

有关字符串基本方法大家好,我又回来了! 之前的几期我们已经简单了解了pandas的基础操作,但是只要涉及到数据,最常见的就是String(字符串)类型,所以很多时候我们其实都在和字符串打交道,所以今天,我会把我自己总结的,有关字符串的常用方法分享给大家,希望能够帮到各位小伙伴~Split and formatlatitude = ‘37.24N’longitude = ‘-115.81W’‘Coordinates {0},{1}’.format(latitude,longitude)>>> ‘Coordinates 37.24N,-115.81W’f’Coordinates {latitude},{longitude}’>>>‘Coordinates 37.24N,-115.81W’’{0},{1},{2}’.format((‘abc’))>>>‘a,b,c’coord = {“latitude”:latitude,“longitude”:longitude}‘Coordinates {latitude},{longitude}’.format(**coord)>>>‘Coordinates 37.24N,-115.81W’Access argument’ s attributeclass Point: def init(self,x,y): self.x,self.y = x,y def str(self): return ‘Point({self.x},{self.y})’.format(self = self) def repr(self): return f’Point({self.x},{self.y})’test_point = Point(4,2)test_point>>> Point(4,2)str(Point(4,2))>>>‘Point(4,2)‘Replace with %s , %r :" repr() shows the quote {!r}, while str() doesn’t:{!s} “.format(‘a1’,‘a2’)>>> " repr() shows the quote ‘a1’, while str() doesn’t:a2 “Align :’{:<30}’.format(’left aligned’)>>>’left aligned ‘’{:>30}’.format(‘right aligned’)>>>’ right aligned’’{:^30}’.format(‘centerd’)>>>’ centerd ‘’{:^30}’.format(‘centerd’)>>>’centerd*‘Replace with %x , %o :“int:{0:d}, hex:{0:x}, oct:{0:o}, bin:{0:b}".format(42)>>>‘int:42, hex:2a, oct:52, bin:101010’’{:,}’.format(12345677)>>>‘12,345,677’Percentage :points = 19total = 22’Correct answers: {:.2%}’.format(points/total)>>>‘Correct answers: 86.36%‘Date :import datetime as dtf”{dt.datetime.now():%Y-%m-%d}">>>‘2019-03-27’f”{dt.datetime.now():%d_%m_%Y}">>>‘27_03_2019’today = dt.datetime.today().strftime("%d_%m_%Y”)today'27_03_2019’Split without parameters :“this is a test”.split()>>>[’this’, ‘is’, ‘a’, ’test’]Concatenate :‘do’*2>>>‘dodo’orig_string =‘Hello’orig_string+’,World’>>>‘Hello,World’full_sentence = orig_string+’,World’full_sentence>>>‘Hello,World’Check string type , slice,count,strip :strings = [‘do’,’re’,‘mi’]’, ‘.join(strings)>>>‘do, re, mi’‘z’ not in ‘abc’>>> Trueord(‘a’), ord(’#’)>>> (97, 35)chr(97)>>>‘a’s = “foodbar"s[2:5]>>>‘odb’s[:4] + s[4:]>>>‘foodbar’s[:4] + s[4:] == s>>>Truet=s[:]id(s)>>>1547542895336id(t)>>>1547542895336s is t>>>Trues[0:6:2]>>>‘fob’s[5:0:-2]>>>‘ado’s = ’tomorrow is monday’reverse_s = s[::-1]reverse_s>>>‘yadnom si worromot’s.capitalize()>>>‘Tomorrow is monday’s.upper()>>>‘TOMORROW IS MONDAY’s.title()>>>‘Tomorrow Is Monday’s.count(‘o’)>>> 4"foobar”.startswith(‘foo’)>>>True"foobar".endswith(‘ar’)>>>True"foobar".endswith(‘oob’,0,4)>>>True"foobar".endswith(‘oob’,2,4)>>>False"My name is yo, I work at SG".find(‘yo’)>>>11# If can’t find the string, return -1"My name is ya, I work at Gener".find(‘gent’)>>>-1# Check a string if consists of alphanumeric characters"abc123".isalnum()>>>True"abc%123".isalnum()>>>False"abcABC".isalpha()>>>True"abcABC1".isalpha()>>>False'123’.isdigit()>>>True'123abc’.isdigit()>>>False’abc’.islower()>>>True"This Is A Title".istitle()>>>True"This is a title".istitle()>>>False’ABC’.isupper()>>>True’ABC1%’.isupper()>>>True’foo’.center(10)>>>’ foo ’’ foo bar baz ‘.strip()>>>‘foo bar baz’’ foo bar baz ‘.lstrip()>>>‘foo bar baz ’’ foo bar baz ‘.rstrip()>>>’ foo bar baz’“foo abc foo def fo ljk “.replace(‘foo’,‘yao’)>>>‘yao abc yao def fo ljk ‘‘www.realpython.com’.strip(‘w.moc’)>>>‘realpython’‘www.realpython.com’.strip(‘w.com’)>>>‘realpython’‘www.realpython.com’.strip(‘w.ncom’)>>>‘realpyth’Convert to lists :’, ‘.join([‘foo’,‘bar’,‘baz’,‘qux’])>>>‘foo, bar, baz, qux’list(‘corge’)>>>[‘c’, ‘o’, ‘r’, ‘g’, ’e’]’:’.join(‘corge’)>>>‘c⭕r:g:e’‘www.foo’.partition(’.’)>>>(‘www’, ‘.’, ‘foo’)‘foo@@bar@@baz’.partition(’@@’)>>>(‘foo’, ‘@@’, ‘bar@@baz’)‘foo@@bar@@baz’.rpartition(’@@’)>>>(‘foo@@bar’, ‘@@’, ‘baz’)‘foo.bar’.partition(’@@’)>>>(‘foo.bar’, ‘’, ‘’)# By default , rsplit split a string with white space’foo bar adf yao’.rsplit()>>>[‘foo’, ‘bar’, ‘adf’, ‘yao’]‘foo.bar.adf.ert’.split(’.’)>>>[‘foo’, ‘bar’, ‘adf’, ’ert’]‘foo\nbar\nadfa\nlko’.splitlines()>>>[‘foo’, ‘bar’, ‘adfa’, ’lko’]总结除了我以上总结的这些,还有太多非常实用的方法,大家可以根据自己的需求去搜索啦!我把这一期的ipynb文件和py文件放到了Github上,大家如果想要下载可以点击下面的链接:Github仓库地址: https://github.com/yaozeliang/pandas_share希望大家能够继续支持我,完结,撒花 ...

March 28, 2019 · 2 min · jiezi

Pandas之旅(四) : 可能是社区内最实用的Pandas技巧

Pandas不为人知的七大实用技巧大家好,我今天勤快地回来了,这一期主要是和大家分享一些pandas的实用技巧,会在日常生活中大大提升效率,希望可以帮助到大家,还是老样子,先给大家奉上这一期的章节目录:自定义pandas选项,设置实用pandas中testing模块构建测试数据巧用accessor访问器合并其他列拼接DatetimeIndex使用分类数据(Categorical Data)节省时间和空间利用Mapping巧妙实现映射压缩pandas对象源码及GitHub地址好啦,话不多说,让我们一个个看吧1. 自定义pandas选项,设置首先,大家可能不知道,pandas里面有一个方法pd.set_option(),利用它我们可以改变一些pandas中默认的核心设置,从而适应我们自身的需要,开始前还是老样子,让我们先导入numpy和pandas包import numpy as npimport pandas as pdf’Using {pd.name}, Version {pd.version}‘‘Using pandas, Version 0.23.0’现在让我们编写一个start方法来实现自定义pandas设置def start(): options = { ‘display’: { ‘max_columns’: None, ‘max_colwidth’: 25, ’expand_frame_repr’: False, # Don’t wrap to multiple pages ‘max_rows’: 14, ‘max_seq_items’: 50, # Max length of printed sequence ‘precision’: 4, ‘show_dimensions’: False }, ‘mode’: { ‘chained_assignment’: None # Controls SettingWithCopyWarning } } for category, option in options.items(): for op, value in option.items(): pd.set_option(f’{category}.{op}’, value) # Python 3.6+if name == ‘main’: start() del start # Clean up namespace in the interpreter大家可以发现,我们在方法的最后调用了pandas的set_option方法,直接利用我们自定义的参数替代了原有的pandas参数,现在让我们测试一下:pd.get_option(‘display.max_rows’)Out:14可以发现max_rows 已经被替换成了我们设置的14,现在用一个真实的例子,我们利用一组公开的鲍鱼各项指标的数据来实验,数据源来自机器学习平台的公开数据url = (‘https://archive.ics.uci.edu/ml/' ‘machine-learning-databases/abalone/abalone.data’)cols = [‘sex’, ’length’, ‘diam’, ‘height’, ‘weight’, ‘rings’]abalone = pd.read_csv(url, usecols=[0, 1, 2, 3, 4, 8], names=cols)abalone sex length diam height weight rings 0 M 0.455 0.365 0.095 0.5140 15 1 M 0.350 0.265 0.090 0.2255 7 2 F 0.530 0.420 0.135 0.6770 9 3 M 0.440 0.365 0.125 0.5160 10 4 I 0.330 0.255 0.080 0.2050 7 5 I 0.425 0.300 0.095 0.3515 8 6 F 0.530 0.415 0.150 0.7775 20 … … … … … … … 4170 M 0.550 0.430 0.130 0.8395 10 4171 M 0.560 0.430 0.155 0.8675 8 4172 F 0.565 0.450 0.165 0.8870 11 4173 M 0.590 0.440 0.135 0.9660 10 4174 M 0.600 0.475 0.205 1.1760 9 4175 F 0.625 0.485 0.150 1.0945 10 4176 M 0.710 0.555 0.195 1.9485 12 我们可以看到,数据截断为14行,保留了小数点后4位小数作为精度,和我们刚刚设置的precision=4是一样的2. 实用pandas中testing模块构建测试数据通过pandas.util.testing提供的方法,我们可以很容易的通过几行代码就构建出一个简单的测试数据类型,比如我们现在构建一个DataTime类型的数据,时间间隔为月:import pandas.util.testing as tmtm.N, tm.K = 15, 3 # 规定行和列import numpy as npnp.random.seed(444)tm.makeTimeDataFrame(freq=‘M’).head() # 设置时间间隔为月# tm.makeTimeDataFrame(freq=‘D’).head() 设置时间间隔为天 A B C 2000-01-31 0.3574 -0.8804 0.2669 2000-02-29 0.3775 0.1526 -0.4803 2000-03-31 1.3823 0.2503 0.3008 2000-04-30 1.1755 0.0785 -0.1791 2000-05-31 -0.9393 -0.9039 1.1837 瞎生成一组乱七八糟的数据:tm.makeDataFrame().head() A B C nTLGGTiRHF -0.6228 0.6459 0.1251 WPBRn9jtsR -0.3187 -0.8091 1.1501 7B3wWfvuDA -1.9872 -1.0795 0.2987 yJ0BTjehH1 0.8802 0.7403 -1.2154 0luaYUYvy1 -0.9320 1.2912 -0.2907 关于可以随机生成的数据类型, 一共大概有30多种,大家如果感兴趣可以多试试:[i for i in dir(tm) if i.startswith(‘make’)][‘makeBoolIndex’, ‘makeCategoricalIndex’, ‘makeCustomDataframe’, ‘makeCustomIndex’, ‘makeDataFrame’, ‘makeDateIndex’, ‘makeFloatIndex’, ‘makeFloatSeries’, ‘makeIntIndex’, ‘makeIntervalIndex’, ‘makeMissingCustomDataframe’, ‘makeMissingDataframe’, ‘makeMixedDataFrame’, ‘makeMultiIndex’, ‘makeObjectSeries’, ‘makePanel’, ‘makePeriodFrame’, ‘makePeriodIndex’, ‘makePeriodPanel’, ‘makePeriodSeries’, ‘makeRangeIndex’, ‘makeStringIndex’, ‘makeStringSeries’, ‘makeTimeDataFrame’, ‘makeTimeSeries’, ‘makeTimedeltaIndex’, ‘makeUIntIndex’, ‘makeUnicodeIndex’]这样我们如果有测试的需求,会很容易地构建相对应的假数据来测试。3. 巧用accessor访问器accessor(访问器) 具体就是类似getter和setter,当然,Python里面不提倡存在setter和getter方法,但是这样可以便于大家理解,pandas Series类型有3类accessor:pd.Series.accessorsOut:{‘cat’, ‘dt’, ‘str’}.cat用于分类数据,.str用于字符串(对象)数据,.dt用于类似日期时间的数据。让我们从.str开始看:假设现在我们有一些原始的城市/州/ 邮编数据作为Dataframe的一个字段:addr = pd.Series([ ‘Washington, D.C. 20003’, ‘Brooklyn, NY 11211-1755’, ‘Omaha, NE 68154’, ‘Pittsburgh, PA 15211’])addr.str.upper() # 因为字符串方法是矢量化的,这意味着它们在没有显式for循环的情况下对整个数组进行操作0 WASHINGTON, D.C. 200031 BROOKLYN, NY 11211-17552 OMAHA, NE 681543 PITTSBURGH, PA 15211dtype: objectaddr.str.count(r’\d’) # 查看邮编有几位0 51 92 53 5dtype: int64如果我们想把每一行分成城市,州,邮编分开,可以用正则;regex = (r’(?P<city>[A-Za-z ]+), ’ # One or more letters r’(?P<state>[A-Z]{2}) ’ # 2 capital letters r’(?P<zip>\d{5}(?:-\d{4})?)’) # Optional 4-digit extensionaddr.str.replace(’.’, ‘’).str.extract(regex) city state zip 0 Washington DC 20003 1 Brooklyn NY 11211-1755 2 Omaha NE 68154 3 Pittsburgh PA 15211 第二个访问器.dt用于类似日期时间的数据。它其实属于Pandas的DatetimeIndex,如果在Series上调用,它首先转换为DatetimeIndexdaterng = pd.Series(pd.date_range(‘2018’, periods=9, freq=‘Q’)) # 时间间隔为季度daterng0 2018-03-311 2018-06-302 2018-09-303 2018-12-314 2019-03-315 2019-06-306 2019-09-307 2019-12-318 2020-03-31dtype: datetime64[ns]daterng.dt.day_name()0 Saturday1 Saturday2 Sunday3 Monday4 Sunday5 Sunday6 Monday7 Tuesday8 Tuesdaydtype: objectdaterng[daterng.dt.quarter > 2] # 查看2019年第3季度和第4季度2 2018-09-303 2018-12-316 2019-09-307 2019-12-31dtype: datetime64[ns]daterng[daterng.dt.is_year_end] #查看年末的一天3 2018-12-317 2019-12-31dtype: datetime64[ns]最后有关.cat访问器我们会在第5个技巧中提到4. 合并其他列拼接DatetimeIndex现在先让我们构建一个包含时间类型数据的Dataframe:from itertools import productdatecols = [‘year’, ‘month’, ‘day’]df = pd.DataFrame(list(product([2017, 2016], [1, 2], [1, 2, 3])), columns=datecols)df[‘data’] = np.random.randn(len(df))df year month day data 0 2017 1 1 -0.0767 1 2017 1 2 -1.2798 2 2017 1 3 0.4032 3 2017 2 1 1.2377 4 2017 2 2 -0.2060 5 2017 2 3 0.6187 6 2016 1 1 2.3786 7 2016 1 2 -0.4730 8 2016 1 3 -2.1505 9 2016 2 1 -0.6340 10 2016 2 2 0.7964 11 2016 2 3 0.0005 我们可以发现year,month,day是分开的三列,我们如果想要把它们合并为完整的时间并作为df的索引,可以这么做:df.index = pd.to_datetime(df[datecols])df.head() year month day data 2017-01-01 2017 1 1 -0.0767 2017-01-02 2017 1 2 -1.2798 2017-01-03 2017 1 3 0.4032 2017-02-01 2017 2 1 1.2377 2017-02-02 2017 2 2 -0.2060 我们可以扔掉没用的列并把这个df压缩为Series:df = df.drop(datecols, axis=1).squeeze()df.head()2017-01-01 -0.07672017-01-02 -1.27982017-01-03 0.40322017-02-01 1.23772017-02-02 -0.2060Name: data, dtype: float64type(df)pandas.core.series.Seriesdf.index.dtype_str’datetime64[ns]‘5. 使用分类数据(Categorical Data)节省时间和空间刚刚我们在第3个技巧的时候提到了访问器,现在让我们来看最后一个.catpandas中Categorical这个数据类型非常强大,通过类型转换可以让我们节省变量在内存占用的空间,提高运算速度,不过有关具体的pandas加速实战,我会在下一期说,现在让我们来看一个小栗子:colors = pd.Series([ ‘periwinkle’, ‘mint green’, ‘burnt orange’, ‘periwinkle’, ‘burnt orange’, ‘rose’, ‘rose’, ‘mint green’, ‘rose’, ’navy’])import syscolors.apply(sys.getsizeof)0 591 592 613 594 615 536 537 598 539 53dtype: int64我们首先创建了一个Series,填充了各种颜色,接着查看了每个地址对应的颜色所占内存的大小注意这里我们使用sys.getsizeof()来获取占内存大小,但是实际上空格也是占内存的,sys.getsizeof(’’)返回的是49bytes接下来我们想把每种颜色用占内存更少的数字来表示(机器学习种非常常见),这样可以减少占用的内存,首先让我们创建一个mapper字典,给每一种颜色指定一个数字mapper = {v: k for k, v in enumerate(colors.unique())}mapper{‘periwinkle’: 0, ‘mint green’: 1, ‘burnt orange’: 2, ‘rose’: 3, ’navy’: 4}接着我们把刚才的colors数组转化为int类型:# 也可以通过 pd.factorize(colors)[0] 实现as_int = colors.map(mapper)as_int0 01 12 23 04 25 36 37 18 39 4dtype: int64再让我们看一下占用的内存:as_int.apply(sys.getsizeof)0 241 282 283 244 285 286 287 288 289 28dtype: int64现在可以观察到我们的内存占用的空间几乎是之前的一半,其实,刚刚我们做的正是模拟Categorical Data的转化原理。现在让我们直接调用一下:colors.memory_usage(index=False, deep=True)Out:650colors.astype(‘category’).memory_usage(index=False, deep=True)Out: 495大家可能感觉节省的空间并不是非常大对不对? 因为目前我们这个数据根本不是真实场景,我们仅仅把数据容量增加10倍,现在再让我们看看效果:manycolors = colors.repeat(10)len(manycolors) / manycolors.nunique() # Much greater than 2.0x Out:20.0f"Not using category : { manycolors.memory_usage(index=False, deep=True)}"‘Not using category : 6500’f"Using category : { manycolors.astype(‘category’).memory_usage(index=False, deep=True)}"‘Using category : 585’这回内存的占用量差距明显就出来了,现在让我们用.cat来简化一下刚刚的工作:new_colors = colors.astype(‘category’)new_colors0 periwinkle1 mint green2 burnt orange3 periwinkle4 burnt orange5 rose6 rose7 mint green8 rose9 navydtype: categoryCategories (5, object): [burnt orange, mint green, navy, periwinkle, rose]new_colors.cat.categories # 可以使用.cat.categories查看代表的颜色Index([‘burnt orange’, ‘mint green’, ’navy’, ‘periwinkle’, ‘rose’], dtype=‘object’)现在让我们查看把颜色代表的数字:new_colors.cat.codes0 31 12 03 34 05 46 47 18 49 2dtype: int8我们如果不满意顺序也可以从新排序:new_colors.cat.reorder_categories(mapper).cat.codes0 01 12 23 04 25 36 37 18 39 4dtype: int8有关cat其他的方法,我们还是可以通过遍历dir来查看:[i for i in dir(new_colors.cat) if not i.startswith(’’)][‘add_categories’, ‘as_ordered’, ‘as_unordered’, ‘categories’, ‘codes’, ‘ordered’, ‘remove_categories’, ‘remove_unused_categories’, ‘rename_categories’, ‘reorder_categories’, ‘set_categories’]Categorical 数据通常不太灵活,比如我们不能直接在new_colors上新增一个新的颜色,要首先通过.add_categories来添加ccolors.iloc[5] = ‘a new color’—————————————————————————NameError Traceback (most recent call last)<ipython-input-36-1766a795336d> in <module>()—-> 1 ccolors.iloc[5] = ‘a new color’NameError: name ‘ccolors’ is not definednew_colors = new_colors.cat.add_categories([‘a new color’])new_colors.iloc[5] = ‘a new color’ # 不会报错new_colors.values # 成功添加6. 利用Mapping巧妙实现映射假设现在我们有存贮国家的一组数据,和一组用来映射国家所对应的大洲的数据:countries = pd.Series([ ‘United States’, ‘Canada’, ‘Mexico’, ‘Belgium’, ‘United Kingdom’, ‘Thailand’])groups = { ‘North America’: (‘United States’, ‘Canada’, ‘Mexico’, ‘Greenland’), ‘Europe’: (‘France’, ‘Germany’, ‘United Kingdom’, ‘Belgium’)}我们可以通过下面的方法来实现简单的映射:from typing import Anydef membership_map(s: pd.Series, groups: dict, fillvalue: Any=-1) -> pd.Series: # Reverse & expand the dictionary key-value pairs groups = {x: k for k, v in groups.items() for x in v} return s.map(groups).fillna(fillvalue) membership_map(countries, groups, fillvalue=‘other’)很简单对不对,现在让我们看一下最关键的一行代码,groups = {x: k for k, v in groups.items() for x in v},这个是我之前提到过的字典推导式:test = dict(enumerate((‘ab’, ‘cd’, ‘xyz’))){x: k for k, v in test.items() for x in v}7. 压缩pandas对象如果你的pandas版本大于0.21.0,那么都可以直接把pandas用压缩形式写入,常见的类型有gzip, bz2, zip,这里我们直接用刚才鲍鱼的数据集:abalone.to_json(‘df.json.gz’, orient=‘records’,lines=True, compression=‘gzip’) # 压缩为gz类型abalone.to_json(‘df.json’, orient=‘records’, lines=True) #压缩为jsonimport os.pathos.path.getsize(‘df.json’) / os.path.getsize(‘df.json.gz’) #压缩大小差了10倍,还是gz更厉害8. 源码及GitHub地址这一期为大家总结了很多pandas实用的小技巧,希望大家喜欢我把这一期的ipynb文件和py文件放到了Github上,大家如果想要下载可以点击下面的链接:Github仓库地址: https://github.com/yaozeliang/pandas_share这一期就到这里啦,希望大家能够继续支持我,完结,撒花 ...

March 19, 2019 · 5 min · jiezi

Pandas之旅(三)最实用的Merge, Join,Concat方法详解

Merge, Join, Concat大家好,我有回来啦,这周更新的有点慢,主要是因为我更新了个人简历哈哈,如果感兴趣的朋友可以去看看哈:我的主页个人认为还是很漂亮的~,不得不说,很多时候老外的设计能力还是很强。好了,有点扯远了,这一期我想和大家分享的是pandas中最常见的几种方法,这些方法如果你学会了,某种程度上可以很好的替代Excel,这篇文章是pandas之旅的第三篇,主要会从以下几个方面和大家分享我的心得体会:MergeJoinConcat源码及GitHub地址话不多说,让我们开始今天的Pandas之旅吧!1. Merge首先merge的操作非常类似sql里面的join,实现将两个Dataframe根据一些共有的列连接起来,当然,在实际场景中,这些共有列一般是Id,连接方式也丰富多样,可以选择inner(默认),left,right,outer 这几种模式,分别对应的是内连接,左连接,右连接1.1 InnerMerge (内连接)首先让我们简单的创建两个DF,分别为DataFrame1,DataFrame2,他们的公有列是keyimport numpy as npimport pandas as pdfrom pandas import Series, DataFrame# Let’s make a dframedframe1 = DataFrame({‘key’:[‘X’,‘Z’,‘Y’,‘Z’,‘X’,‘X’],‘value_df1’: np.arange(6)})dframe1 key value_df1 0 X 0 1 Z 1 2 Y 2 3 Z 3 4 X 4 5 X 5 #Now lets make another dframedframe2 = DataFrame({‘key’:[‘Q’,‘Y’,‘Z’],‘value_df2’:[1,2,3]})dframe2 key value_df2 0 Q 1 1 Y 2 2 Z 3 我们现在可以简单地使用pd.merge(dframe1,dframe2)来实现Merge功能pd.merge(dframe1,dframe2) key value_df1 value_df2 0 Z 1 3 1 Z 3 3 2 Y 2 2 我们现在需要注意一点,X仅仅是存在于dframe1的key,在dframe2中不存在,因此大家可以发现,当我们调用pd.merge的时候,会自动默认为inner join,我们再换一种方式写一下,大家就明白了:pd.merge(dframe1,dframe2,on=‘key’,how=‘inner’) key value_df1 value_df2 0 Z 1 3 1 Z 3 3 2 Y 2 2 大家可以发现结果是一样的,看到这里,对sql熟悉的朋友们已经有感觉了估计,因为实在是太像了,如果我们不通过on和how来指定想要merge的公有列或者方式,那么pd.merge就会自动寻找到两个DataFrame的相同列并自动默认为inner join,至此,估计大家也可以猜出其他几种模式的merge啦1.2 LeftMerge (左连接)现在同样的,让我们看一下how=‘left’的情况,这是一个左连接pd.merge(dframe1,dframe2,on=‘key’,how=‘left’) key value_df1 value_df2 0 X 0 NaN 1 Z 1 3.0 2 Y 2 2.0 3 Z 3 3.0 4 X 4 NaN 5 X 5 NaN 我们可以看到返回的是dframe1的所有key值对应的结果,如果在dframe2中不存在,显示为Nan空值1.3 RightMerge (右连接)右连接的原理和左连接正相反pd.merge(dframe1,dframe2,on=‘key’,how=‘right’) key value_df1 value_df2 0 Z 1.0 3 1 Z 3.0 3 2 Y 2.0 2 3 Q NaN 1 这里Q只存在于drame2的key中1.4 OuterMerge (全连接)#Choosing the “outer” method selects the union of both keyspd.merge(dframe1,dframe2,on=‘key’,how=‘outer’) key value_df1 value_df2 0 X 0.0 NaN 1 X 4.0 NaN 2 X 5.0 NaN 3 Z 1.0 3.0 4 Z 3.0 3.0 5 Y 2.0 2.0 6 Q NaN 1.0 这里就是一个并集的形式啦,其实就是一个union的结果,会把key这一列在两个Dataframe出现的所有值全部显示出来,如果有空值显示为Nan1.5 MultipleKey Merge (基于多个key上的merge)刚才我们都是仅仅实现的在一个key上的merge,当然我们也可以实现基于多个keys的merge# Dframe on leftdf_left = DataFrame({‘key1’: [‘SF’, ‘SF’, ‘LA’], ‘key2’: [‘one’, ’two’, ‘one’], ’left_data’: [10,20,30]})df_left key1 key2 left_data 0 SF one 10 1 SF two 20 2 LA one 30 #Dframe on rightdf_right = DataFrame({‘key1’: [‘SF’, ‘SF’, ‘LA’, ‘LA’], ‘key2’: [‘one’, ‘one’, ‘one’, ’two’], ‘right_data’: [40,50,60,70]})df_right key1 key2 right_data 0 SF one 40 1 SF one 50 2 LA one 60 3 LA two 70 这是内连接(交集)的结果#Merge, Innerpd.merge(df_left, df_right, on=[‘key1’, ‘key2’]) key1 key2 left_data right_data 0 SF one 10 40 1 SF one 10 50 2 LA one 30 60 这是外连接(并集)的结果#Merge, Outerpd.merge(df_left, df_right, on=[‘key1’, ‘key2’],how=‘outer’) key1 key2 left_data right_data 0 SF one 10.0 40.0 1 SF one 10.0 50.0 2 SF two 20.0 NaN 3 LA one 30.0 60.0 4 LA two NaN 70.0 这里还有一个地方非常有意思,大家可以发现现在df_left,df_right作为key的两列分别是key1和key2,它们的名字是相同的,刚刚我们是通过制定on=[‘key1’, ‘key2’],那如果我们只指定一列会怎么样呢?pd.merge(df_left,df_right,on=‘key1’) key1 key2_x left_data key2_y right_data 0 SF one 10 one 40 1 SF one 10 one 50 2 SF two 20 one 40 3 SF two 20 one 50 4 LA one 30 one 60 5 LA one 30 two 70 大家可以看到pandas自动把key2这一列拆分成了key2_x和key2_y,都会显示在最后的merge结果里,如果我们想要给这两列重新命名,也是很容易的:# We can also specify what the suffix becomespd.merge(df_left,df_right, on=‘key1’,suffixes=(’_lefty’,’_righty’)) key1 key2_lefty left_data key2_righty right_data 0 SF one 10 one 40 1 SF one 10 one 50 2 SF two 20 one 40 3 SF two 20 one 50 4 LA one 30 one 60 5 LA one 30 two 70 像这样,我们可以通过suffixes参数来指定拆分的列的名字。1.6 Merge on Index (基于index上的merge)我们还可以实现几个Dataframe基于Index的merge,还是老样子,先让我们创建两个Dataframedf_left = DataFrame({‘key’: [‘X’,‘Y’,‘Z’,‘X’,‘Y’], ‘data’: range(5)})df_right = DataFrame({‘group_data’: [10, 20]}, index=[‘X’, ‘Y’])df_left key data 0 X 0 1 Y 1 2 Z 2 3 X 3 4 Y 4 df_right group_data X 10 Y 20 好了,现在我们想要实现两个Dataframe的merge,但是条件是通过df_left的Key和df_right的Indexpd.merge(df_left,df_right,left_on=‘key’,right_index=True) key data group_data 0 X 0 10 3 X 3 10 1 Y 1 20 4 Y 4 20 这样我们也可以得到结果。# We can also get a union by using outerpd.merge(df_left,df_right,left_on=‘key’,right_index=True,how=‘outer’) key data group_data 0 X 0 10.0 3 X 3 10.0 1 Y 1 20.0 4 Y 4 20.0 2 Z 2 NaN 其他的merge方式就类似啦,这里就不一一说了,只是举一个outer join的例子# 通过outer实现外连接,union并集pd.merge(df_left,df_right,left_on=‘key’,right_index=True,how=‘outer’) key data group_data 0 X 0 10.0 3 X 3 10.0 1 Y 1 20.0 4 Y 4 20.0 2 Z 2 NaN 我们也可以尝试一些有意思的merge,比如,如果一个dataframe的index是多层嵌套的情况:df_left_hr = DataFrame({‘key1’: [‘SF’,‘SF’,‘SF’,‘LA’,‘LA’], ‘key2’: [10, 20, 30, 20, 30], ‘data_set’: np.arange(5.)})df_right_hr = DataFrame(np.arange(10).reshape((5, 2)), index=[[‘LA’,‘LA’,‘SF’,‘SF’,‘SF’], [20, 10, 10, 10, 20]], columns=[‘col_1’, ‘col_2’])df_left_hr key1 key2 data_set 0 SF 10 0.0 1 SF 20 1.0 2 SF 30 2.0 3 LA 20 3.0 4 LA 30 4.0 df_right_hr col_1 col_2 LA 20 0 1 10 2 3 SF 10 4 5 10 6 7 20 8 9 现在我们穿建了两个Dataframe 分别是df_left_hr和df_right_hr(Index两层),如果我们想通过使用df_left_hr的key1,key2 及df_right_hr的Index作为merge的列,也是没有问题的# Now we can merge the left by using keys and the right by its indexpd.merge(df_left_hr,df_right_hr,left_on=[‘key1’,‘key2’],right_index=True) key1 key2 data_set col_1 col_2 0 SF 10 0.0 4 5 0 SF 10 0.0 6 7 1 SF 20 1.0 8 9 3 LA 20 3.0 0 1 基本到这里,我已经和大家分享了基础的Merge有关的所有操作,如果你平时生活工作中经常使用Excel执行类似操作的话,可以学习一下Merge哈,它会大幅度减轻你的工作强度的!2.Join现在我们可以接着来看join相关的操作,先让我们看一个小例子left = pd.DataFrame({‘A’: [‘A0’, ‘A1’, ‘A2’, ‘A3’], ‘B’: [‘B0’, ‘B1’, ‘B2’, ‘B3’]}, index = [‘K0’, ‘K1’, ‘K2’, ‘K3’]) right = pd.DataFrame({‘C’: [‘C0’, ‘C1’, ‘C2’, ‘C3’], ‘D’: [‘D0’, ‘D1’, ‘D2’, ‘D3’]}, index = [‘K0’, ‘K1’, ‘K2’, ‘K3’]) left A B K0 A0 B0 K1 A1 B1 K2 A2 B2 K3 A3 B3 right C D K0 C0 D0 K1 C1 D1 K2 C2 D2 K3 C3 D3 left.join(right) A B C D K0 A0 B0 C0 D0 K1 A1 B1 C1 D1 K2 A2 B2 C2 D2 K3 A3 B3 C3 D3 其实通过这一个小例子大家也就明白了,join无非就是合并,默认是横向,还有一个点需要注意的是,我们其实可以通过join实现和merge一样的效果,但是为了避免混淆,我不会多举其他的例子了,因为我个人认为一般情况下还是用merge函数好一些3. Concat为了更加全面彻底地了解Concat函数,大家可以先从一维的Numpy Array开始,首先让我们简单的创建一个矩阵:# Create a matrix arr1 = np.arange(9).reshape((3,3))arr1array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])接着让我们通过concatenate函数进行横向拼接:np.concatenate([arr1,arr1],axis=1)array([[0, 1, 2, 0, 1, 2], [3, 4, 5, 3, 4, 5], [6, 7, 8, 6, 7, 8]])再让我们进行纵向拼接:# Let’s see other axis optionsnp.concatenate([arr1,arr1],axis=0)array([[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 1, 2], [3, 4, 5], [6, 7, 8]])有了基础的印象之后,现在让我们看看在pandas中是如何操作的:# Lets create two Series with no overlapser1 = Series([0,1,2],index=[‘T’,‘U’,‘V’])ser2 = Series([3,4],index=[‘X’,‘Y’])#Now let use concat (default is axis=0)pd.concat([ser1,ser2])T 0U 1V 2X 3Y 4dtype: int64在上面的例子中,我们分别创建了两个没有重复Index的Series,然后用concat默认的把它们合并在一起,这时生成的依然是Series类型,如果我们把axis换成1,那生成的就是Dataframe,像下面一样pd.concat([ser1,ser2],axis=1,sort =True) # sort=Ture是默认的,pandas总是默认index排序 0 1 T 0.0 NaN U 1.0 NaN V 2.0 NaN X NaN 3.0 Y NaN 4.0 我们还可以指定在哪些index上进行concat:pd.concat([ser1,ser2],axis=1,join_axes=[[‘U’,‘V’,‘Y’]]) 0 1 U 1.0 NaN V 2.0 NaN Y NaN 4.0 也可以给不同组的index加一层标签pd.concat([ser1,ser2],keys=[‘cat1’,‘cat2’])cat1 T 0 U 1 V 2cat2 X 3 Y 4dtype: int64如果把axis换成是1,那么keys就会变成column的名字:pd.concat([ser1,ser2],axis=1,keys=[‘cat1’,‘cat2’],sort=True) cat1 cat2 T 0.0 NaN U 1.0 NaN V 2.0 NaN X NaN 3.0 Y NaN 4.0 如果是两个现成的dataframe直接进行concat也是一样:dframe1 = DataFrame(np.random.randn(4,3), columns=[‘X’, ‘Y’, ‘Z’])dframe2 = DataFrame(np.random.randn(3, 3), columns=[‘Y’, ‘Q’, ‘X’])dframe1 X Y Z 0 1.119976 -0.853960 0.027451 1 -0.536831 0.982092 -0.157650 2 -0.219322 -1.489809 1.607735 3 0.767249 -1.661912 0.038837 dframe2 Y Q X 0 -0.035560 0.875282 -1.630508 1 -0.439484 0.096247 1.335693 2 0.746299 0.568684 1.197015 #如果没有对应的值,默认为NaN, 空值pd.concat([dframe1,dframe2],sort=True) Q X Y Z 0 NaN 1.119976 -0.853960 0.027451 1 NaN -0.536831 0.982092 -0.157650 2 NaN -0.219322 -1.489809 1.607735 3 NaN 0.767249 -1.661912 0.038837 0 0.875282 -1.630508 -0.035560 NaN 1 0.096247 1.335693 -0.439484 NaN 2 0.568684 1.197015 0.746299 NaN 4. 源码及Github地址今天我为大家主要总结了pandas中非常常见的三种方法:mergeconcatjoin大家可以根据自己的实际需要来决定使用哪一种我把这一期的ipynb文件和py文件放到了Github上,大家如果想要下载可以点击下面的链接:Github仓库地址: https://github.com/yaozeliang/pandas_share这一期就到这里啦,希望大家能够继续支持我,完结,撒花 ...

March 17, 2019 · 5 min · jiezi

seaborn 0.9 文档翻译活动期待大家的参与~

参与方式:https://github.com/apachecn/s…整体进度:https://github.com/apachecn/s…项目仓库:https://github.com/apachecn/s…贡献指南请您勇敢地去翻译和改进翻译。虽然我们追求卓越,但我们并不要求您做到十全十美,因此请不要担心因为翻译上犯错——在大部分情况下,我们的服务器已经记录所有的翻译,因此您不必担心会因为您的失误遭到无法挽回的破坏。(改编自维基百科)负责人:飞龙:562826179章节列表An introduction to seabornInstalling and getting startedVisualizing statistical relationshipsPlotting with categorical dataVisualizing the distribution of a datasetVisualizing linear relationshipsBuilding structured multi-plot gridsControlling figure aestheticsChoosing color palettesseaborn.relplotseaborn.scatterplotseaborn.lineplotseaborn.catplotseaborn.stripplotseaborn.swarmplotseaborn.boxplotseaborn.violinplotseaborn.boxenplotseaborn.pointplotseaborn.barplotseaborn.countplotseaborn.jointplotseaborn.pairplotseaborn.distplotseaborn.kdeplotseaborn.rugplotseaborn.lmplotseaborn.regplotseaborn.residplotseaborn.heatmapseaborn.clustermapseaborn.FacetGridseaborn.FacetGrid.mapseaborn.FacetGrid.map_dataframeseaborn.PairGridseaborn.PairGrid.mapseaborn.PairGrid.map_diagseaborn.PairGrid.map_offdiagseaborn.PairGrid.map_lowerseaborn.PairGrid.map_upperseaborn.JointGridseaborn.JointGrid.plotseaborn.JointGrid.plot_jointseaborn.JointGrid.plot_marginalsseaborn.setseaborn.axes_styleseaborn.set_styleseaborn.plotting_contextseaborn.set_contextseaborn.set_color_codesseaborn.reset_defaultsseaborn.reset_origseaborn.set_paletteseaborn.color_paletteseaborn.husl_paletteseaborn.hls_paletteseaborn.cubehelix_paletteseaborn.dark_paletteseaborn.light_paletteseaborn.diverging_paletteseaborn.blend_paletteseaborn.xkcd_paletteseaborn.crayon_paletteseaborn.mpl_paletteseaborn.choose_colorbrewer_paletteseaborn.choose_cubehelix_paletteseaborn.choose_light_paletteseaborn.choose_dark_paletteseaborn.choose_diverging_paletteseaborn.load_datasetseaborn.despineseaborn.desaturateseaborn.saturateseaborn.set_hls_values流程一、认领首先查看整体进度,确认没有人认领了你想认领的章节。然后回复 ISSUE,注明“章节 + QQ 号”(一定要留 QQ)。二、翻译可以合理利用翻译引擎(例如谷歌),但一定要把它变得可读!如果遇到格式问题,请随手把它改正。三、提交fork Github 项目将译文放在docs文件夹下pushpull request请见 Github 入门指南。

March 14, 2019 · 1 min · jiezi

Pandas之旅(二): 有关数据清理的点点滴滴

数据清洗大家好,这一期我将为大家带来我的pandas学习心得第二期:数据清理。这一步非常重要,一般在获取数据源之后,我们紧接着就要开始这一步,以便为了之后的各种操作,简单来说,我们的目标就是让数据看起来赏心悦目,规规矩矩的,所以我们会对原始的dataframe做一些必要的美容,包括规范命名,去除异常值,重新选择合适的index啊,处理缺失值,统一列的命名等等。这一期我会和大家分享一些比较好用常见的清洗方法。首先还是让我们来简单看一下本文将会用到的数据源:property_data.csv 这是一个超小型的房地产行业的数据集,大家会在文章最后找到下载地址。这篇文章我会从以下几个方面来和大家分享我的心得体会:有关缺失值的处理有关列的处理设置Index源码及数据下载地址1.有关缺失值的处理这里我们会用到 property_data.csv这个数据集,在开始处理缺失值之前,我们可以先话一分钟仔细想想,为什么实际生活中的数据从来是不完整的,原因基本有几个方面:用户忘记填写字段从旧数据库手动传输时数据丢失代码中有bug用户不填写非必须字段(比如注册的时候)因为这些原因,我每次在处理missing value的时候都会问自己两个基础问题:数据集每一列有什么特点?我们想要在处理后得到什么类型的数据(int,float,string,boolean)?带着这些疑问,我们可以开始了,首先让我们简单读取一下数据,利用head函数看看前5行,如果你还对pandas的基础知识有疑问,可以看看我上一篇文章:Pandas之旅(一): 让我们把基础知识一次撸完,申精干货import pandas as pdimport numpy as npimport osos.chdir(“F:\Python教程\segmentfault\pandas_share\Pandas之旅_02 数据清洗”)# Read csv file into a pandas dataframedf = pd.read_csv(“property_data.csv”)# Take a look at the first few rowsdf.head() PID ST_NUM ST_NAME OWN_OCCUPIED NUM_BEDROOMS NUM_BATH SQ_FT 0 100001000.0 104.0 PUTNAM Y 3 1 1000 1 100002000.0 197.0 LEXINGTON N 3 1.5 – 2 100003000.0 NaN LEXINGTON N NaN 1 850 3 100004000.0 201.0 BERKELEY 12 1 NaN 700 4 NaN 203.0 BERKELEY Y 3 2 1600 现在让我们看看数据的一些关键列是什么:ST_NUM:街道号码ST_NAME: 街道名称OWN_OCCUPIED: 是否用于自住NUM_BEDROOMS:卧室数量SQ_FT:面积这里可以给大家普及点房地产知识,有的时候房屋用途被明确规定,比如有的房产写的是"owner occupied only “)意思是说如果你买了,那这个房子会成为你的主要住所,不能用于出租之类的,简单理解就是自住所以现在我可以自问自答第一个问题:数据集每一列有什么特点?ST_NUM:float或int …ST_NAME:stringOWN_OCCUPIED:string … Y(“是”)或N(“否”)NUM_BEDROOMS:float或int,数字类型SQ_FT:float或int,数字类型1.1 规范的缺失值标记现在让我们关注ST_NUM这一列:# Looking at the ST_NUM columndf[‘ST_NUM’]0 104.01 197.02 NaN3 201.04 203.05 207.06 NaN7 213.08 215.0Name: ST_NUM, dtype: float64如果想查看该列的缺失值情况,我们可以利用isnull()方法,如果出现缺失值,会返回True,反之返回falsedf[‘ST_NUM’].isnull()0 False1 False2 True3 False4 False5 False6 True7 False8 FalseName: ST_NUM, dtype: bool但是其实如果我们打开csv文件,你会发现第3行是空白,还有一行在该列显示的是NA,所以结论已经有了:在pandas里表示缺省值的符号及时NA,换句话说,如果我们要表示缺省值,标准写法是NA1.2 不规范的缺失值标记同样的,这回让我们关注一下NUM_BEDROOMS这一列,我们发现出现了4种类型的表达缺省值的标记:n/aNA—na通过刚才的实践,我们已经确定NA是pandas可以识别的,那么其他的符号呢,现在让我们来测试一下df[‘NUM_BEDROOMS’]0 31 32 NaN3 14 35 NaN6 27 18 naName: NUM_BEDROOMS, dtype: objectdf[‘NUM_BEDROOMS’].isnull()0 False1 False2 True3 False4 False5 True6 False7 False8 FalseName: NUM_BEDROOMS, dtype: bool可以看到pandas识别了n/a 和NA两种符号,但是接下来我们要考虑一个问题,假设你是房地产公司的地区总经理,你每周会收到不同地区的负责人提交的表格,这些人中有的喜欢用–表示空白值,有的人喜欢用na,那应该怎么办?最简单的方式就是将所有表示空白值的符号统一放在list中,让后让pandas一次性识别:# Making a list of missing value typesmissing_values = [“na”, “–"]df = pd.read_csv(“property_data.csv”, na_values = missing_values)现在我们来看看到底发生了什么?df PID ST_NUM ST_NAME OWN_OCCUPIED NUM_BEDROOMS NUM_BATH SQ_FT 0 100001000.0 104.0 PUTNAM Y 3.0 1 1000.0 1 100002000.0 197.0 LEXINGTON N 3.0 1.5 NaN 2 100003000.0 NaN LEXINGTON N NaN 1 850.0 3 100004000.0 201.0 BERKELEY 12 1.0 NaN 700.0 4 NaN 203.0 BERKELEY Y 3.0 2 1600.0 5 100006000.0 207.0 BERKELEY Y NaN 1 800.0 6 100007000.0 NaN WASHINGTON NaN 2.0 HURLEY 950.0 7 100008000.0 213.0 TREMONT Y 1.0 1 NaN 8 100009000.0 215.0 TREMONT Y NaN 2 1800.0 我们可以发现只要missing_value中记录的表达空白值的符号,全部变成了规整的NaN1.3 类型不一致的异常值刚刚我们已经简单了解了在pandas中如何处理缺失值的,还有一种情况,让我们来看OWN_OCCUPIED这一列,这一列的答案只能是Y,N 但是我们发现数据集意外地出现了12,属于类型不对称df[‘OWN_OCCUPIED’].isnull()0 False1 False2 False3 False4 False5 False6 True7 False8 FalseName: OWN_OCCUPIED, dtype: bool现在我们发现12是异常值,因为它是类型错误,所以我们可以简单通过下面这个方法来检测,# Detecting numbers cnt=0for row in df[‘OWN_OCCUPIED’]: try: int(row) df.loc[cnt, ‘OWN_OCCUPIED’]=np.nan except ValueError: pass cnt+=1我们这里的策略是:循环遍历OWN_OCCUPIED列尝试将条目转换为整数如果条目可以更改为整数,请输入缺失值如果数字不能是整数,我们知道它是一个字符串,所以继续这样我们会把OWN_OCCUPIED这一列中所有类型不对的值转化为NaN,现在来看结果:df[‘OWN_OCCUPIED’]0 Y1 N2 N3 NaN4 Y5 Y6 NaN7 Y8 YName: OWN_OCCUPIED, dtype: object1.4 汇总缺失值pandas提供了更为简洁的方式,可以让我们整体了解所有column的空值:df.isnull().sum()PID 1ST_NUM 2ST_NAME 0OWN_OCCUPIED 2NUM_BEDROOMS 3NUM_BATH 1SQ_FT 2dtype: int64或者如果我们只想知道数据是否存在空值,那么可以使用以下的命令:# Any missing values?df.isnull().values.any()True1.5 替换缺失值如果我们想要替换掉缺失值,可以用fillna方法# Replace missing values with a numberdf[‘ST_NUM’].fillna(125, inplace=True)或者我们可以通过准确定位来替换缺失值:# Location based replacementdf.loc[2,‘ST_NUM’] = 125替换缺失值的一种非常常见的方法是使用中位数:# Replace using median median = df[‘NUM_BEDROOMS’].median()df[‘NUM_BEDROOMS’].fillna(median, inplace=True)df PID ST_NUM ST_NAME OWN_OCCUPIED NUM_BEDROOMS NUM_BATH SQ_FT 0 100001000.0 104.0 PUTNAM Y 3.0 1 1000.0 1 100002000.0 197.0 LEXINGTON N 3.0 1.5 NaN 2 100003000.0 125.0 LEXINGTON N 2.5 1 850.0 3 100004000.0 201.0 BERKELEY NaN 1.0 NaN 700.0 4 NaN 203.0 BERKELEY Y 3.0 2 1600.0 5 100006000.0 207.0 BERKELEY Y 2.5 1 800.0 6 100007000.0 125.0 WASHINGTON NaN 2.0 HURLEY 950.0 7 100008000.0 213.0 TREMONT Y 1.0 1 NaN 8 100009000.0 215.0 TREMONT Y 2.5 2 1800.0 2. 有关列的处理2.1 统一修改列名现在假设因为一些需求,需要我们统一修改列名,把列名改为小写,我们可以结合列表推导式轻易实现df.rename(str.lower, axis=‘columns’,inplace =True)df.columnsIndex([‘pid’, ‘st_num’, ‘st_name’, ‘own_occupied’, ’num_bedrooms’, ’num_bath’, ‘sq_ft’], dtype=‘object’)或者需要把列名中的_改为-:new_cols = [c.replace(”_”,"-") for c in df.columns]change_dict =dict(zip(df.columns,new_cols))df.rename(columns=change_dict,inplace=True)df pid st-num st-name own-occupied num-bedrooms num-bath sq-ft 0 100001000.0 104.0 PUTNAM Y 3.0 1 1000.0 1 100002000.0 197.0 LEXINGTON N 3.0 1.5 NaN 2 100003000.0 125.0 LEXINGTON N 2.5 1 850.0 3 100004000.0 201.0 BERKELEY NaN 1.0 NaN 700.0 4 NaN 203.0 BERKELEY Y 3.0 2 1600.0 5 100006000.0 207.0 BERKELEY Y 2.5 1 800.0 6 100007000.0 125.0 WASHINGTON NaN 2.0 HURLEY 950.0 7 100008000.0 213.0 TREMONT Y 1.0 1 NaN 8 100009000.0 215.0 TREMONT Y 2.5 2 1800.0 这里我没有写的精简一些,反而是复杂了,主要是想让大家回忆起之前我分享的dict使用技巧中的内容,注意这里inplace=True,导致的结果是我们的的确确修改了df所有的列名2.1 根据需求新增列假如目前我们需要新增一列,根据房屋面积大小来赋值,我们先随意把缺失值补上:df[‘sq-ft’].fillna(‘0.0’)0 10001 0.02 8503 7004 16005 8006 9507 0.08 1800Name: sq-ft, dtype: object然后新建一列rank来根据房屋面积大小赋值S=small,M=medium,B=big:df[“rank”]= pd.cut(df[‘sq-ft’], [0, 800, 1600, np.inf], labels=(“S”,“M”,“B”))df pid st-num st-name own-occupied num-bedrooms num-bath sq-ft rank 0 100001000.0 104.0 PUTNAM Y 3.0 1 1000.0 M 1 100002000.0 197.0 LEXINGTON N 3.0 1.5 NaN NaN 2 100003000.0 125.0 LEXINGTON N 2.5 1 850.0 M 3 100004000.0 201.0 BERKELEY NaN 1.0 NaN 700.0 S 4 NaN 203.0 BERKELEY Y 3.0 2 1600.0 M 5 100006000.0 207.0 BERKELEY Y 2.5 1 800.0 S 6 100007000.0 125.0 WASHINGTON NaN 2.0 HURLEY 950.0 M 7 100008000.0 213.0 TREMONT Y 1.0 1 NaN NaN 8 100009000.0 215.0 TREMONT Y 2.5 2 1800.0 B 具体实现方法我们之后会说,这里主要是用到了pandas的cut方法,非常便捷3. 设置Index在许多情况下,使用数据的唯一值标识字段作为其索引是有帮助的。这里可能我们的数据不太合适,因此我们先伪造一列Fake_Index来模拟真实场景中的真正索引df[“Fake_Index”]=[“A00”+str(i) for i in range(len(df))]df pid st-num st-name own-occupied num-bedrooms num-bath sq-ft rank Fake_Index 0 100001000.0 104.0 PUTNAM Y 3.0 1 1000.0 M A000 1 100002000.0 197.0 LEXINGTON N 3.0 1.5 NaN NaN A001 2 100003000.0 125.0 LEXINGTON N 2.5 1 850.0 M A002 3 100004000.0 201.0 BERKELEY NaN 1.0 NaN 700.0 S A003 4 NaN 203.0 BERKELEY Y 3.0 2 1600.0 M A004 5 100006000.0 207.0 BERKELEY Y 2.5 1 800.0 S A005 6 100007000.0 125.0 WASHINGTON NaN 2.0 HURLEY 950.0 M A006 7 100008000.0 213.0 TREMONT Y 1.0 1 NaN NaN A007 8 100009000.0 215.0 TREMONT Y 2.5 2 1800.0 B A008 现在我们添加的最后一列非常像真正的房屋Id了,让我们来看看这个伪造的索引是不是唯一值,可以利用is_unique来检验:df.Fake_Index.is_uniqueTrue没有问题,现在我们可以放心地把这列设置为我们真正的索引:df = df.set_index(‘Fake_Index’)df pid st-num st-name own-occupied num-bedrooms num-bath sq-ft rank Fake_Index A000 100001000.0 104.0 PUTNAM Y 3.0 1 1000.0 M A001 100002000.0 197.0 LEXINGTON N 3.0 1.5 NaN NaN A002 100003000.0 125.0 LEXINGTON N 2.5 1 850.0 M A003 100004000.0 201.0 BERKELEY NaN 1.0 NaN 700.0 S A004 NaN 203.0 BERKELEY Y 3.0 2 1600.0 M A005 100006000.0 207.0 BERKELEY Y 2.5 1 800.0 S A006 100007000.0 125.0 WASHINGTON NaN 2.0 HURLEY 950.0 M A007 100008000.0 213.0 TREMONT Y 1.0 1 NaN NaN A008 100009000.0 215.0 TREMONT Y 2.5 2 1800.0 B 现在对数据的操作容易多了,我们很多事情可以通过索引完成:# 根据索引名称切片df[‘A000’:‘A003’] pid st-num st-name own-occupied num-bedrooms num-bath sq-ft rank Fake_Index A000 100001000.0 104.0 PUTNAM Y 3.0 1 1000.0 M A001 100002000.0 197.0 LEXINGTON N 3.0 1.5 NaN NaN A002 100003000.0 125.0 LEXINGTON N 2.5 1 850.0 M A003 100004000.0 201.0 BERKELEY NaN 1.0 NaN 700.0 S # 根据索引位置切片df.iloc[1:3, 0:3] pid st-num st-name Fake_Index A001 100002000.0 197.0 LEXINGTON A002 100003000.0 125.0 LEXINGTON # 定位到具体元素df.iloc[1,2]‘LEXINGTON’总结我把这一期的ipynb文件和py文件放到了GIthub上,大家如果想要下载可以点击下面的链接:Github仓库地址: https://github.com/yaozeliang/pandas_share这一期先讲到这里,希望大家能够继续支持我,完结,撒花 ...

March 9, 2019 · 5 min · jiezi

Pandas之旅(一): 让我们把基础知识一次撸完,申精干货

为什么你需要pandas大家好,今天想和大家分享一下有关pandas的学习新的,我因工作需要,从去年12月开始接触这个非常好用的包,到现在为止也是算是熟悉了一些,因此发现了它的强大之处,特意想要和朋友们分享,特别是如果你每天和excel打交道,总是需要编写一些vba函数或者对行列进行groupby啊,merge,join啊之类的,相信我,pandas会让你解脱的。好啦,闲话少说,这篇文章的基础是假设你已经大概听说过了pandas的一些概念和用途,如果还大体上不太清楚的朋友们,可以去百度一下相关基础介绍,本分主要分成四个部分:从Dataframe说起 : 简单了解Df这种数据结构,了解如何创建一个DfDataframe基础操作 :基于行,列,index选取数据,新增数据,删除数据Pandas 读取 / 导出数据: 了解如何对excel,csv,tsv等常见文件进行读取并导出总结: 精华部分,为大家总结一些非常实用的一些方法,并附带源码 ipynb以及py文件提供下载1. 从Dataframe说起首先,让我们明确一点,pandas这个包是在numpy的基础上得到的,因此可能有的朋友会有疑问,要不要先学学numpy,我的个人建议是真的不太需要,因为大多数的情况下基本用不到,当然,如果你处理的是科学实验类型的数据的话,当我没说,我这里的应用场景主要是一般类型的常见数据,比如:你是销售经理,经常需要汇总各地区的销售情况你在银行工作,不可避免的需要和数字,excel打交道你每天有很多重复的工作,比如备份,计算两表合并,分组,聚类等等。。。。。。这种情况下,学习pandas会非常有用,这里我们说的数据都是二维的table,在pandas中也称作dataframe。pandas中其实一共有三种类型的常见数据:数据结构维度说明Series1类似list,一维数组Data Frames2最常见的二维数据结构,excel,sql的表就是这个Panel3用的很少,三维结构pandas主要包括三类数据结构,分别是:Series:一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近,其区别是:List中的元素可以是不同的数据类型,而Array和Series中则只允许存储相同的数据类型,这样可以更有效的使用内存,提高运算效率。DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。以下的内容主要以DataFrame为主。Panel :三维的数组,可以理解为DataFrame的容器。Pandas官网,更多功能请参考 http://pandas-docs.github.io/…这里我们主要聚焦在Dataframe上,一个dataframe长的基本上如下这番模样:NameAgeMarkJohn1578Mike2386Mary3695我们把这个简单的dataframe起个名字叫df,那么它包括的最基础的元素有:index:每行的索引,默认是从0开始,比如上面的df[0] 就是指 John 15 78这一行,依次类推,当然我们可以自己规定index,我以后会说columns:列。这里就是指的是Name Age Mark 了rows:行,df一共有3行现在让我们看一个完整的图示:Dataframe 是应用最多也是最广泛的数据结构,现在就让我们开始学习创建一个dataframe吧~1.1 创建Dataframe创建一个Dataframe的方法有很多,总体上来说最常见的有及种:创建空dataframe利用dict创建从其他数据源读取(网站,excel,mysql等)真实场景中大多数都是从其他数据源读取,我们会在第3部分讲到创建空dataframe这个非常简单:import pandas as pd # Calling DataFrame constructor df = pd.DataFrame() print(df)Out:Empty DataFrame Columns: [] Index: []利用dict创建(1)import pandas as pdprint (f" Using {pd.name},Version {pd.version}")Out: Using pandas , version 0.23.4首先要import pandas 包,这里缩写为pd,现在让我们从dict创建一个dataframe:>>> dict = {’name’:[“Tom”, “Bob”, “Mary”, “James”], ‘age’: [18, 30, 25, 40], ‘city’:[“Beijing”, “ShangHai”,“GuangZhou”, “ShenZhen”]} >>> df = pd.DataFrame(dict) >>> df创建结果如下: age city name 0 18 Beijing Tom 1 30 ShangHai Bob 2 25 GuangZhou Mary 3 40 ShenZhen James 很简单是不是,大家可能发现了,最左边的东西就是index ,0,1,2,3,如果我们不指定会自动生成从0默认开始的序列,一直到你的dataframe的最后一行,类似于excel左边的编号利用dict创建(2)这次让我们创建的更加规范一些:index = pd.Index([“Tom”, “Bob”, “Mary”, “James”],name = ‘person’)cols = [‘age’,‘city’]data = [[18,‘Beijing’], [30,‘ShangHai’], [25,‘GuangZhou’], [40,‘ShenZhen’]]df =pd.DataFrame(index = index,data =data,columns = cols)df age city person Tom 18 Beijing Bob 30 ShangHai Mary 25 GuangZhou James 40 ShenZhen 这里的主要区别在于我们主动规定了‘name’列为索引。这种把一列默认为索引的方式在excel和sql里都有,异曲同工从其他数据源读取(网站,excel,mysql等)我会在第三部分介绍最常用的从excel,csv等读取数据总体来说,有关创建Dataframe的部分我们不用了解太多,因为实际的场景基本不需要,都是直接从csv,tsv,sql,json等数据源直接获取。2. Dataframe 基础操作这里我们主要看一下基于索引,行,列,行和列的基础操作,最后会为大家总结一下,现在拿刚刚我们创建过的dataframe为例: age city name 0 18 Beijing Tom 1 30 ShangHai Bob 2 25 GuangZhou Mary 3 40 ShenZhen James 2.1 对columns的基础操作添加新列添加一列非常简单:df[‘country’] = ‘USA’df age city name country 0 18 Beijing Tom USA 1 30 ShangHai Bob USA 2 25 GuangZhou Mary USA 3 40 ShenZhen James USA df[‘adress’] = df[‘country’]df age city name country adress 0 18 Beijing Tom USA USA 1 30 ShangHai Bob USA USA 2 25 GuangZhou Mary USA USA 3 40 ShenZhen James USA USA 修改列中的值修改一个列的值也是很容易的,我们可以这样做:df[‘country’] = ‘China’df age city name country adress 0 18 Beijing Tom China USA 1 30 ShangHai Bob China USA 2 25 GuangZhou Mary China USA 3 40 ShenZhen James China USA 或者稍微多想一步:df[‘adress’] = df[‘city’]+’,’+ df[‘country’]df age city name country adress 0 18 Beijing Tom China Beijing,China 1 30 ShangHai Bob China ShangHai,China 2 25 GuangZhou Mary China GuangZhou,China 3 40 ShenZhen James China ShenZhen,China 删除列我们可以应用del或者drop函数,如果是drop,要注意传参时要加上axis = 1.这里简单和大家说明一下axis,这个东西其实就是指轴向,默认的axis=0,是纵向,axis=1是横向df.drop(‘country’,axis=1)df age city name adress 0 18 Beijing Tom Beijing,China 1 30 ShangHai Bob ShangHai,China 2 25 GuangZhou Mary GuangZhou,China 3 40 ShenZhen James ShenZhen,China del df[‘city’]df age name adress 0 18 Tom Beijing,China 1 30 Bob ShangHai,China 2 25 Mary GuangZhou,China 3 40 James ShenZhen,China 这里有一点大家需要注意:drop和del的结果是基于df的两次单独操作,并不是连续的如果我们执行完drop后,重新查看df,这时你会发现df没有变化,因为没有真正的删除要想真正删除,需要加上关键字 inplace = True因此如果我们想要连续删除country和city这两列,改进后的代码如下:df.drop(‘country’,axis=1, inplace=True)del df[‘city’]df age name adress 0 18 Tom Beijing,China 1 30 Bob ShangHai,China 2 25 Mary GuangZhou,China 3 40 James ShenZhen,China 选取列这个非常简单,实现代码如下:df[‘age’] # 选取age这一列 0 18 1 30 2 25 3 40 Name: age, dtype: int64或者这样:df.name 0 Tom 1 Bob 2 Mary 3 James Name: name, dtype: object如果想要选取多个列也很容易,传递一个list就行啦:df[[‘age’,’name’]] age name 0 18 Tom 1 30 Bob 2 25 Mary 3 40 James 这里注意,和选取单独一列不同,这里我们返回的类型是dataframe,之前的类型是series,我们可以这么理解,一列其实还是一维数组,但是两列及以上是二维的了,当然类型也变了如果我们想要查看当前的所有列:df.columnsOut:Index([u’age’, u’name’, u’adress’], dtype=‘object’)如果我们想要重新对列进行命名,基本有三种方法,大家挑一种自己喜欢的就行传递list传递dict传递 axis用list:df.columns = [‘Age’,‘Name’,‘Adress’]df用dict:df.rename(index = str, columns = {‘age’:‘Age’,’name’:‘Name’,‘adress’:‘Adress’}) #这里index=str 有没有都行,我这么做是为了规范df用axis:df.rename(str.capitalize, axis=‘columns’,inplace =True)df最后得到的效果是一样的: Age Name Adress 0 18 Tom Beijing,China 1 30 Bob ShangHai,China 2 25 Mary GuangZhou,China 3 40 James ShenZhen,China 根据条件给列赋值我们现在想要根据人的年龄新增一列 Group,假设要求如下:18岁以下的是年轻人18-30的是中年人30以上的是老年人我们有很多方法可以实现,先看一种,大家可以先忽视loc方法,这里传达的就是基础思路:df[‘Group’] = ’elderly’df.loc[df[‘Age’]<=18, ‘Group’] = ‘young’df.loc[(df[‘Age’] >18) & (df[‘Age’] <= 30), ‘Group’] = ‘middle_aged’df Age Name Adress Group 0 18 Tom Beijing,China young 1 30 Bob ShangHai,China middle_aged 2 25 Mary GuangZhou,China middle_aged 3 40 James ShenZhen,China elderly 2.2 对 rows 的基础操作loc函数 df.loc[row,column]首先,大多数对于行的操作都可以通过loc函数实现,比如我们想要选取全部的行,除了直接打出df外,可以使用df.loc[:]df.loc[:] Age Name Adress Group 0 18 Tom Beijing,China young 1 30 Bob ShangHai,China middle_aged 2 25 Mary GuangZhou,China middle_aged 3 40 James ShenZhen,China elderly loc函数条件查询df.loc[df[‘Age’]>20] Name Age Adress Group 1 Bob 30 ShangHai,China middle_aged 2 Mary 25 GuangZhou,China middle_aged 3 James 40 ShenZhen,China elderly loc函数条件行列查询df.loc[df[‘Group’]==‘middle_aged’,‘Name’]1 Bob2 MaryName: Name, dtype: objectWhere 查询filter_adult = df[‘Age’]>25result = df.where(filter_adult)result Name Age Adress Group 0 NaN NaN NaN NaN 1 Bob 30.0 ShangHai,China middle_aged 2 NaN NaN NaN NaN 3 James 40.0 ShenZhen,China elderly Query 筛选# df.query(‘Age==30’) df.query(‘Group==“middle_aged”‘and ‘Age>30’ ) Name Age Adress Group 3 James 40 ShenZhen,China elderly 2.3 对 Dataframe 的基础了解这里有很多有用的方法,可以帮助到大家大致了解数据的情况:df.shape # 了解行列情况Out:(4, 4)df.describe() # 获取可计算列基础统计 Age count 4.000000 mean 28.250000 std 9.251126 min 18.000000 25% 23.250000 50% 27.500000 75% 32.500000 max 40.000000 # df.head(3) #查看前三行数据,默认为5df.tail(3) #获得最后三行数据 Name Age Adress Group 1 Bob 30 ShangHai,China middle_aged 2 Mary 25 GuangZhou,China middle_aged 3 James 40 ShenZhen,China elderly 3. Pandas读取导出数据(csv)Pandas 支持大部分常见数据文件读取与存储。一般清楚下,读取文件的方法以 pd.read_ 开头,而写入文件的方法以 pd.to_ 开头。这里我们开始熟悉一下最实用的对于csv文件的读取写入写入CSVdf.to_csv(‘person.csv’,index=None,sep=’,’)import osos.getcwd()Out: ‘C:\Users\E560’这样大家就可以在’C:UsersE560’的路径下找到我们刚刚生成的csv文件了,这里我把index=None,舍弃了索引值读取CSV首先我们确认和python文件同一目录下存在我们刚刚导出的person.csv文件,之后可以很容易的读取了:person = pd.read_csv(‘person.csv’)person Name Age Adress Group 0 Tom 18 Beijing,China young 1 Bob 30 ShangHai,China middle_aged 2 Mary 25 GuangZhou,China middle_aged 3 James 40 ShenZhen,China elderly 这时我们发现,即使我们读取的csv文件没有索引,但是pandas已经默认帮我们加上了4. 总结,资料下载好了,现在大家对pandas的使用已经有了基础的印象,我给大家简单总结一下常用的方法:使用标签选取数据df.loc[行标签,列标签]df.loc[‘Tom’:‘Mary’] #选取 Tom至Mary的所有行的数据,Tom和Mary是indexdf.loc[:,‘city’] #选取 city 列的数据df.loc 的第一个参数是行标签,第二个参数为列标签(可选参数,默认为所有列标签),两个参数既可以是列表也可以是单个字符,如果两个参数都为列表则返回的是 DataFrame,否则,则为 Series。PS:loc为location的缩写。使用位置(index)选取数据df.iloc[行位置,列位置] df.iloc[1,1] #选取第二行,第二列的值,返回的为单个值 df.iloc[[0,2],:] #选取第一行及第三行的数据 df.iloc[0:2,:] #选取第一行到第三行(不包含)的数据 df.iloc[:,1] #选取所有记录的第二列的值,返回的为一个Series df.iloc[1,:] #选取第一行数据,返回的为一个SeriesPS:iloc 则为 integer & location 的缩写通过逻辑指针进行数据切片df[逻辑条件]df[df.age >= 18] #单个逻辑条件df[(df.age >=18 ) & (df.country==‘China’) ] #多个逻辑条件组合了解并掌握数据大致情况方法解释count非na值的数量describe针对Series或个DataFrame列计算汇总统计min、max计算最小值和最大值argmin、argmax计算能够获取到最大值和最小值得索引位置(整数)idxmin、idxmax计算能够获取到最大值和最小值得索引值quantile计算样本的分位数(0到1)sum值的总和mean值得平均数median值得算术中位数(50%分位数)mad根据平均值计算平均绝对离差var样本值的方差std样本值的标准差skew样本值得偏度(三阶矩)kurt样本值得峰度(四阶矩)cumsum样本值得累计和cummin,cummax样本值得累计最大值和累计最小值cumprod样本值得累计积diff计算一阶差分(对时间序列很有用)pct_change计算百分数变化常见读取写入数据数据类型读取写入CSVread_csvto_csvJSONread_jsonto_jsonHTMLread_htmlto_htmlEXCELread_excelto_excelSQLread_sqlto_sql好了,其实这些就是想要告诉大家如何学习pandas,没有必要了解每一个方法,但是现在想必你知道pandas能实现的功能很多,这样你有具体需求时只要详细查询一下文档即可,接下来几期我们会重点来看pandas里面对于df的各种操作,从简单的数据清理到类似于excel里面的vba,包括cancat,merge,join等等下载我把这一期的ipynb文件和py文件放到了GIthub上,大家如果想要下载可以点击下面的链接:Github仓库地址: 点我下载好啦,这一期就讲这么多,希望大家能够继续支持我,完结,撒花 ...

March 4, 2019 · 4 min · jiezi

Python 进阶之路 (十二) 尾声即是开始

Python进阶之路总结大家好,我的<< Python进阶之路>>到这一期就到此为止了,和 <<Python 基础起步>>不同,在掌握了一些基础知识后,我在这一期里同步和大家分享了我的学习心得,一共主要关注了以下几个知识点:Python 进阶之路 (一) List 进阶方法汇总Python 进阶之路 (二) Dict 进阶宝典Python 进阶之路 (三) Tuple元组使用指南Python 进阶之路 (四) 先立Flag, 社区最全的Set用法集锦Python 进阶之路 (五) map, filter, reduce, zip 一网打尽Python 进阶之路 (六) 九浅一深 lambda,陈独秀你给我坐下!Python 进阶之路 (七) 隐藏的神奇宝藏:探秘CollectionsPython 进阶之路 (八) 最用心的推导式详解Python 进阶之路 (九) 再立Flag, 社区最全的itertools深度解析(上)Python 进阶之路 (十) 再立Flag, 社区最全的itertools深度解析(中)Python 进阶之路 (十一) 再立Flag, 社区最全的itertools深度解析(下)现在看来,除了标题起的比较活泼外,考虑到我也是小白,内容上我自认为已经是干货满满了,如果你打开任何一篇文章,相信你会发现我并没有夸大,没有任何一篇文章是蜻蜓点水,一带而过,对得起花时间观看文章的每一位朋友,从2月4日第一遍笔记起,22天更新了11篇,应该说高产似母猪了今天是进阶之路的最后一篇文章,然而像标题所示,尾声即是开始,现在我们中午掌握了python的基础知识,哪怕可能不够熟练,但是足够开始新的征程了!我决定新的旅途让我们从pandas开始,原因有很多,我会在结尾和大家说明,现在还是老规矩,我将和大家分享我在学习过程中发现的一些非常不错的资源,没有它们的帮助不论如何我是写不出这些文章的。优秀资源分享在我的Python基础起步系列的最后,我分享了很多优秀资源给大家,这回也不例外,在此我将把写文章期间参考的非常优秀的资源分享给大家,让我们一起进步:综合教程文章 / 视频:Corey Schafer的youtube视频教程,个人认为是最好的视频教程,需要翻墙Py4e,密歇根大学的教程,有详细PPT 可以下载RealPython 由浅入深来学习,我最爱闲逛的网站,我的文章很多是受上面的教程启发DataCamp 很棒的免费教程,付费部分暂不需要Tutorial Point不错的免费教程,个人感觉比w3school强GeeksforGeeks非常棒的综合Python教程平台,我目前碰到的几乎所有问题,都会在上面找到答案Pythonforbeginers非常不错的起步教程,界面简单明了廖雪峰老师的教程,不用多说,名声很大了进阶文档Python设计模式及实用方法Intermediate Python一个很火的python技巧文档在线测试onlinegdb 一个非常好用的在线环境,支持所有语言,做一些简单功能测试的时候很方便,有代码补充提示,可以在线保存新专栏Pandas我想了一段时间,不太确定要先和大家分享OOP编程思想还是Pandas,最后还是决定新建一个Pandas专栏教程,因为现在数据分析非常普遍。相关的工作岗位也很多,同时我自己在工作中应用pandas也比较多,对我而言会更容易一些。从实用性角度讲也是如此,如果你平时的工作涉及到大量的 excel 或者 VBA,那么 pandas 无意是你最好的选择。这次我计划的新专栏会和你常见的不太一样。经过我简单的个人研究,我发现pandas教程遍地都是,但是很多教程的问题如下:一次能讲完的东西,拆分成好几节课没有及时更新,很多停留在2016年或者之前缺少自己的理解和基础模型分享有些收费的课程水分很大我这次会尽我所能,为大家带来干货版本的pandas学习心得,争取用5期达到他人10期的效果,同时会加入一些工作中遇到的,自己创建的,别人教我的小模型等。争取让我的免费分享达到别人收费的标准当然,由于pandas是应用于数据分析的第三方包,分享时会涉及到大量图表,因此我会使用Jupyter Notebook作为环境和编辑器,每期教程后也会和大家分享源代码,这次会正式一些,直接放在 github 里,只希望得到大家的鼓励,并且真正帮助到有需要的人。名词解释:有需要的人:只要你平时用 excel,就是有需要!!!最后想说,多谢很多朋友的鼓励支持,我作为新手注册SegmentFault并开专栏起,已经做好了迎接各种吐槽的准备,然而这种情况并没有出现,除了大家比较善良外,主要原因是没多少人关注 不过慢慢地,在写文章的过程中,我发现也有很多朋友和我一样,是以萌新的身份进入编程领域的。对于这些朋友我想说,你不是一个人在战斗,在学习Python的路上战友越多,就会越轻松,大家互相分享,终会成长,我不否认世上有很多天才,但是大多数时候,一个人的智慧很难和群体抗衡。因此我希望大家可以在我的文章下多多留言,让我在修改错误的同时也能和你一起进步!就这样,让我们下期 Pandas见

February 27, 2019 · 1 min · jiezi

ApacheCN 学习资源汇总 2019.1

【主页】 apachecn.org【Github】@ApacheCN暂时下线: 社区暂时下线: cwiki 知识库自媒体平台微博:@ApacheCN知乎:@ApacheCNCSDN简书OSChina博客园我们不是 Apache 的官方组织/机构/团体,只是 Apache 技术栈(以及 AI)的爱好者!合作or侵权,请联系【fonttian】<fonttian@gmail.com> | 请抄送一份到 <apachecn@163.com>Java 基础Java 编程思想Java Web 和大数据Spark 2.2.0 中文文档Storm 1.1.0 中文文档Kafka 1.0.0 中文文档Beam 中文文档Zeppelin 0.7.2 中文文档Elasticsearch 5.4 中文文档Kibana 5.2 中文文档Kudu 1.4.0 中文文档Spring Boot 1.5.2 中文文档Airflow 中文文档区块链Solidity 中文文档数学笔记MIT 18.06 线性代数笔记Python 数据科学NumPy 中文文档Pandas 中文文档Matplotlib 中文文档UCB Data8 课本:计算与推断思维UCB Prob140 课本:面向数据科学的概率论UCB DS100 课本:数据科学的原理与技巧利用 Python 进行数据分析 · 第 2 版fast.ai 数值线性代数讲义 v2Pandas Cookbook 带注释源码statsmodels 中文文档数据科学 IPython 笔记本CS 教程LeetCode 中文文档GeeksForGeeks 翻译计划UCB CS61a 课本:SICP Python 描述UCB CS61b 课本:Java 中的数据结构数据结构思维中国大学 MOOC 计算机操作系统笔记简单数据结构实现AI 教程AILearning - 机器学习实战Sklearn 与 TensorFlow 机器学习实用指南面向机器学习的特征工程Python 数据分析与挖掘实战(带注释源码)SciPyCon 2018 Sklearn 教程TensorFlow 学习指南fast.ai 机器学习和深度学习中文笔记HackCV 网站文章翻译台湾大学林轩田机器学习笔记Scikit-learn 秘籍写给人类的机器学习数据科学和人工智能技术笔记AI 文档Sklearn 0.19 中文文档PyTorch 1.0 中文文档XGBoost 中文文档LightGBM 中文文档FastText 中文文档Gensim 中文文档AI 比赛Kaggle 项目实战教程:文档 + 代码 + 视频比赛收集平台其它独立开发/自由职业/远程工作资源列表通往财富自由之路精细笔记5 分钟商学院精细笔记 ...

January 29, 2019 · 1 min · jiezi

使用Opencv构建一个简单的图像相似检测器(MSE、SSIM)

摘要: 本文使用opencv。numpy等简单的工具库,根据mse及ssim两种算法来评估两张图像的相似度,便于理解与实践。介绍作为人类,我们通常非常善于发现图像中的差异。例如,常见的游戏——两张图像找不同。现在让我们玩下这个游戏吧,首先让我们看看上面的图像,三十秒内看看是否能够从中找出有什么不同的地方。答案:水果、冰淇淋和饮料的颜色发生了明显改变,窗帘、太阳也发生了改变,这是不是很简单呢?如果有补充的答案,请在留言处给出哦!这类问题对于人类来说看起来是一件轻而易举的事情,但是,对于计算机来说,这可不是一件容易的事儿。这是由于计算机只能从我们训练它的模型中学习,才最终具有这类能力。目前有很多很好的模型可以对批量图像进行分类,比如TensorFlow和Keras等开源工具。借助于这类开源工具库,计算机视觉领域的研究得以高发展。现在我们也可以借助于这类工具箱创建非常复杂的模型以及解决比较复杂的问题,例如kaggle:Animals-10,该数据集包含数十种不同类型动物的图像以及非动物图像。所要做的就是创建一个模型来预测图片是哪种类型的动物。MSE和SSIM然而,上述任务较为简单,比如常见的手写体数字识别MNIST等,一般也都能取得很高的精度。在这里,我想增加一点难度,创建一个图像分类器,以分辨出两个图像的相似程度。并且,不依赖任何复杂的工具库,如TensorFlow、Keras等。本文采用传统的机器学习方法,这里从中选取两种方法,用于查找图像是否与另一个图像相似。这两种方法分别为均方误差(MSE)、结构相似度指数(SSIM)。上述公式看起来非常复杂,但不要害怕。借助于NumPy,可以相当容易地计算出MSE;另外,由于SSIM是Sci-Kit图像库的内置方法的一部分,因此也可以很容易地计算出SSIM。在进行编码之前,这里先对这两种方法予以简单的说明。MSE将计算正在比较的两个图像的每个像素之间的均方误差。而SSIM做的事情与MSE恰好相反,寻找像素值的相似之处。 也就是,如果两个图像中的像素排列相似或具有相似的像素密度值。MSE方法遇到的一个的问题是其结果往往具有任意大的值,因此很难给出标准的评判标准。一般而言,MSE越高,表明两张图像的相似程度越低。如果图像之间的MSE值是随机值,则很难说明二者是否相似。另一方面,SSIM将所有内容归一化到-1~1的范围内(很难得到小于0的分数)。得分为1表示二者非常相似,得分为-1表示二者非常不同。基于此,SSIM相较于MSE而言是一个更好的衡量指标。实现现在使用代码实现上述想法:加载必要的库:本文使用常见的图像处理工具箱OpenCV实现图像的读取和编辑。如果你对其它图像处理工具箱熟悉,你也可以使用自己熟悉的工具箱完成此类操作,比如matplotlibden。编写MSE公式:使用Numpy操作起来很简单吧!由于SSIM已经通过skimage导入,因此无需进行手动编码。现在创建一个比较函数,该函数的输入为两个图像,分别计算二者的MSE和SSIM,并展示计算结果。下面的三个步骤可以使用for循环一次完成,但是为了更容易地理解,这里不使用for循环编写代码,将其分解为三个部分:首先,加载保存在目录中的图像。其次,必须确保它们的大小相同,否则会出现尺寸不匹配的错误。问题是对其进行尺寸变换操作会导致图像失真,所以在找到比较合适的尺寸数字之前,可以尝试快速搜索方法,尺寸大小按照一定的规律设置,不断实验以找到最终比较合适的尺寸。接下来我们再实现一个功能,以便于看到测试图像是什么样子的。现在通过比较两个一样的图像来测试并查看MSE和SSIM是否正常工作。如果它有效,那么我们应该得到MSE值为0和SSIM值为1的结果。从中可以看到,代码正确,结果与猜想的一致!现在计算机就可以判断比较的两张图像是否相同了。为简单起见,我将三张狗的图像与自己以及三张猫的图像进行比较。下面看看两种算法的性能比较。正如所看到的那样,MSE的值变化很大,因此该值很难说明其表达的意思是什么。但从SSIM的结果看出,可以看到狗2和狗3相对于其他狗的图像最为相似。从视觉上来讲,我同意这个结果,因为两只狗的耳朵非常像。但我还会认为狗1和狗3会有更高的SSIM值,因为二者的姿势也很相似。实际上,在图像没有进行灰度处理之前,狗2和狗3在鼻子区域周围有类似的白色毛皮,而狗1没有。这很可能是狗2和3具有比狗1更高的SSIM值的原因。对于猫来说,这就有点困难。猫1和猫2具有相似的形状,并且图像是从相似的距离拍摄的,但猫2和猫3具有相似的皮毛颜色。这里我想进行的测试只有两个:一个是狗和猫的相似性,第二个是每个动物与原始源代码附带的门图的相似性。正如所预料的那样,狗和猫是相似的,这点与与无生命的物体相比呈鲜明的对比,如侏罗纪公园入口门。狗和猫对门的图像具有较高的SSIM值,唯一原因在于图像都经过了尺寸缩放和灰度处理。在调整图像大小和重新配置时,OpenCV并不是最好的。一般而言,TensorFlow是最好的,TensorFlow也最适合批量图像。之后,我也将使用TensorFlow处理kaggle Animal-10数据集,来实现一个完整的图像分类器。本文作者:【方向】阅读原文本文为云栖社区原创内容,未经允许不得转载。

January 22, 2019 · 1 min · jiezi

Mars 是什么、能做什么、如何做的——记 Mars 在 PyCon China 2018 上的分享

最近,在 PyCon China 2018 的北京主会场、成都和杭州分会场都分享了我们最新的工作 Mars,基于矩阵的统一计算框架。本文会以文字的形式对 PyCon 中国上的分享再进行一次阐述。听到 Mars,很多第一次听说的同学都会灵魂三问:Mars 是什么,能做什么,怎么做的。今天我们就会从背景,以及一个例子出发,来回答这几个问题。背景首先是 scipy 技术栈的全景图,numpy 是基础,它提供了多维数组的数据结构,并提供了它上面的各种计算。再往上,重要的有 scipy,主要面向各种科学计算的操作;pandas,其中核心的概念是 DataFrame,他提供对表类型数据的处理、清洗等功能。往上一层,比较经典的库,有 scikit-learn,它是最知名的机器学习框架之一。最上面一层,是各种垂直领域的库,如 astropy 主要面向天文,biopython 面向生物领域等。从 scipy 技术栈可以看出,numpy 是一个核心的地位,大量上层的库都使用了 numpy 的数据结构和计算。我们真实世界的数据,并不只是表这种二维类型数据那么简单,很多时候,我们要面对的往往是多维数据,比如我们常见的图片处理,首先我们有图片的个数,然后有图片的长宽,以及 RGBA 通道,这就是四维的数据;这样的例子不胜枚举。有这样多维的处理能力,就有处理各种更加复杂,甚至是科学领域的能力;同时,由于多维数据本身包含二维数据,所以,我们也因此具备表类型数据的处理能力。另外,如果我们需要探究数据的内在,光靠对表数据进行一些统计等操作是绝对不够的,我们需要更深层的“数学” 的方法,比如运用矩阵乘法、傅里叶变换等等的能力,来对数据进行更深层次的分析。而 numpy 由于是数值计算的库,加上各种上层的库,我们认为它们很适合用来提供这方面的能力。为什么要做 Mars,从一个例子开始那么,为什么要做 Mars 这个项目呢?我们不妨从一个例子来看。我们试图用蒙特卡洛方法来求解 pi,蒙特卡洛方法其实很简单,就是用随机数的方法来解决特定的问题。如图,这里我们有个半径为1的圆和边长为2的正方形,我们生成很多随机点的方式,通过右下角的公式,我们就可以计算出 pi 的值为 4 乘以落在圆里点的个数除以总的点个数。随机生成的点越多,计算出来的 pi 就越精确。用纯 Python 实现非常简单,我们只要遍历 N 次,生成 x 和 y 点,计算是不是落在圆内即可。运行1千万个点,需要超过10秒的时间。Cython 是常见加速 Python 代码的方式,Cython 定义了 Python 语言的超集,把这个语言翻译到 c/c++,然后再进行编译来加速执行。这里,我们增加了几个变量的类型,可以看到比纯 Python 提升了 40% 的性能。Cython 现在已经成为 Python 项目的标配,核心的 Python 三方库基本都使用 Cython 来加速 Python 代码的性能。我们这个例子里的数据都是一个类型,我们可以想到用专门的数值计算的库,通过矢量化的方式,能极快加速这个任务的性能。numpy 就是当仁不让的选择了,使用 numpy,我们需要的是面向 array 的思维方式,我们应当减少使用循环。这里先用 numpy.random.uniform 来生成 N2 的一个二维数组,然后 data ** 2 会对该数组里的所有数据做平方操作,然后 sum(axis=1) ,会对 axis=1 也就是行方向上求和,这个时候,得到的是长度为 N 的 vector,然后我们用 numpy.sqrt 来对这个 vector 的每一个值求开方,<1 会得到一个布尔值的 vector,即每个点是不是都是落在圆里,最后接一个 sum,就可以求出来总共的点的个数。初次上手 numpy 可能会不太习惯,但是用多了以后,就会发现这种写法的方便,它其实是非常符合直觉的。可以看到,通过使用 numpy,我们写出了更简单的代码,但是性能确大幅提升,比纯 Python 的写法性能提升超过 10 倍。那么 numpy 的代码还能够优化么,答案是肯定的,我们通过一个叫 numexpr 的库,来将 numpy 的多个操作合并成一个操作执行,来加速 numpy 的执行。可以看到,通过 numexpr 优化的代码,性能比纯 Python 代码提升超过 25 倍。此时的代码运行已经相当快了,如果我们手上有 GPU,那么我们可以利用硬件来加速任务执行。这里必须要安利一个库,叫 cupy,他提供了和 numpy 一致的 API,通过简单的 import 替换,就能让 numpy 代码跑在英伟达的显卡之上。这时可以看到,性能大幅提升超过 270 倍。真的非常夸张了。为了让蒙特卡洛方法计算的结果更加精确,我们把计算量扩大 1000 倍。会碰到什么情况呢?没错,这就是大家不时碰到的,OutOfMemory,内存溢出。更惨的是,在 jupyter 里,有时候内存溢出导致进程被杀,甚至会导致之前跑的全部结果都丢失。蒙特卡洛方法还是比较容易处理的,我把问题分解成 1000 个,每个求解1千万数据就好了嘛,写个循环,做个汇总。但此时,整个计算的时间来到了12分钟多,太慢了。此时我们会发现,整个运行过程中,其实只有一个 CPU 在干活,其他核都在原地吆喝。那么,我们怎么让 numpy 并行化呢?首先,numpy 里有一些操作是能并行的,比如 tensordot 来做矩阵乘法,其他大部分操作都不能利用多核。那么,要将 numpy 并行化,我们可以:采用多线程/多进程编写任务分布式化蒙特卡洛方法算 pi 改写成多线程和多进程实现还是非常容易的,我们写一个函数来处理1千万的数据,我们把这个函数通过 concurrent.futures 的 ThreadPoolExecutor 和 ProcessPoolExecutor 来分别提交函数 1000 遍用多线程和多进程执行即可。可以看到性能能提升到 2倍和3倍。但是呢,蒙特卡洛求解 pi 本身就很容易手写并行,考虑更复杂的情况。import numpy as npa = np.random.rand(100000, 100000)(a.dot(a.T) - a).std()这里创建了 10万10万的矩阵 a,输入就有大概 75G,我们拿 a 矩阵乘 a 的转置,再减去 a 本身,最终求标准差。这个任务的输入数据就很难塞进内存,后续的手写并行就更加困难。这里问题就引出来了,我们需要什么样框架呢?提供熟悉的接口,像 cupy 这样,通过简单的 import 替换,就能让原来 numpy 写的代码并行。具备可扩展性。小到单机,也可以利用多核并行;大到一个很大的集群,支持上千台机器的规模来一起分布式处理任务。支持硬件加速,支持用 GPU 等硬件来加速任务执行。支持各种优化,比如操作合并,能利用到一些库来加速执行合并的操作。我们虽然是内存计算的,但不希望单机或者集群内存不足,任务就会失败。我们应当让暂时用不到的数据 spill 到磁盘等等存储,来保证即使内存不够,也能完成整个计算。Mars 是什么,能做什么事Mars 就是这样一个框架,它的目标就是解决这几个问题。目前 Mars 包括了 tensor :分布式的多维矩阵计算。100亿大小的蒙特卡洛求解 pi的问题规模是 150G,它会导致 OOM。通过 Mars tensor API,只需要将 import numpy as np 替换成 import mars.tensor as mt,后续的计算完全一致。不过有一个不同,mars tensor 需要通过 execute 触发执行,这样做的好处是能够对整个中间过程做尽量多的优化,比如操作合并等等。不过这种方式对 debug 不太友好,后续我们会提供 eager mode,来对每一步操作都触发计算,这样就和 numpy 代码完全一致了。可以看到这个计算时间和手写并行时间相当,峰值内存使用也只是 1个多G,因此可以看到 Mars tensor 既能充分并行,又能节省内存的使用 。目前,Mars 实现了 70% 的常见 numpy 接口,完整列表见 这里。我们一致在努力提供更多 numpy 和 scipy 的接口,我们最近刚刚完成了对逆矩阵计算的支持。Mars tensor 也提供了对 GPU 和稀疏矩阵的支持。eye 是创建单位对角矩阵,它只有对角线上有值为1,如果用稠密的方式存储会浪费存储。不过目前,Mars tensor 还只支持二维稀疏矩阵。Mars 怎么做到并行和更省内存和所有的 dataflow 的框架一样,Mars 本身也有计算图的概念,不同的是,Mars 包含粗粒度图和细粒度图的概念,用户写的代码在客户端生成粗粒度图,在提交到服务端后,会有 tile 的过程,将粗粒度图 tile 成细粒度图,然后我们会调度细粒度图执行。这里,用户写下的代码,在内存里会表达成 Tensor 和 Operand 构成的粗粒度图。当用户调用 execute 方法时,粗粒度的图会被序列化到服务端,反序列化后,我们会把这个图 tile 成细粒度图。对于输入 10002000 的矩阵,假设指定每个维度上的 chunk 大小都是 500,那它会被 tile 成 24 一共 8 个chunk。后续,我们会对每个我们实现的 operand 也就是算子提供 tile 的操作,将一个粗粒度的图 tile 成细粒度图。这时,我们可以看到,在单机,如果有8个核,那么我们就可以并行执行整个细粒度图;另外给定 1/8 大小的内存,我们就可以完成整个图的计算。不过,我们在真正执行前,会对整个图进行 fuse 也就是操作合并的优化,这里的三个操作真正执行的时候,会被合并成一个算子。针对执行目标的不同,我们会使用 numexpr 和 cupy 的 fuse 支持来分别对 CPU 和 GPU 进行操作合并执行。上面的例子,都是我们造出来很容易并行的任务。如我们先前提到的例子,通过 tile 之后生成的细粒度图其实是非常复杂的。真实世界的计算场景,这样的任务其实是很多的。为了将这些复杂的细粒度图能够充分调度执行,我们必须要满足一些基本的准则,才能让执行足够高效。首先,初始节点的分配非常重要。比如上图,假设我们有两个 worker,如果我们把 1和3 分配到一个 worker,而将 2和4 分配到另一个 worker,这时当 5 或者 6 被调度的时候,他们就需要触发远程数据拉取,这样执行效率会大打折扣。如果我们一开始将 1和2 分配到一个 worker,将 3和4 分配到另一个 worker,这时执行就会非常高效。初始节点的分配对整体的执行影响是很大的,这就需要我们对整个细粒度的图有个全局的掌握,我们才能做到比较好的初始节点分配。另外,深度优先执行的策略也是相当重要的。假设这时,我们只有一个 worker,执行完 1和2 后,我们调度了 3 的话,就会导致 1和2 的内存不能释放,因为 5 此时还没有被触发执行。但是,如果我们执行完 1和2 后,调度了 5 执行,那么当 5 执行完后,1和2 的内存就可以释放,这样整个执行过程中的内存就会是最省的。所以,初始节点分配,以及深度优先执行是两个最基本的准则,光有这两点是远远不够的,mars 的整个执行调度中有很多具有挑战的任务,这也是我们需要长期优化的对象。Mars 分布式所以,Mars 本质上其实是一个细粒度的,异构图的调度系统。我们把细粒度的算子调度到各个机器上,在真正执行的时候其实是调用 numpy、cupy、numexpr 等等的库。我们充分利用了成熟的、高度优化的单机库,而不是重复在这些领域造轮子。在这个过程中,我们会遇到一些难点:因为我们是 master-slave 架构,我们 master 如何避免单点?我们的 worker 如何避免 Python 的 GIL(全局解释器锁)的限制?Master 的控制逻辑交错复杂,我们很容易写出来高耦合的,又臭又长的代码,我们如何将代码解耦?我们的解法是使用 Actor model。Actor模型定义了并行的方式,也就是一切皆 Actor,每个 Actor 维护一个内部状态,它们都持有邮箱,Actor 之间通过消息传递,消息收到会放在邮箱中,Actor 从邮箱中取消息进行处理,一个 Actor 同时只能处理一个消息。Actor 就是一个最小的并行单元,由于一个 Actor 同时只能处理一个消息,你完全不需要担心并发的问题,并发应当是 Actor 框架来处理的。而所有 Actor 是不是在同一台机器上,这在 Actor 模型里也变得不重要,Actor 在不同机器上,只要能完成消息的传递就可以了,这样 Actor 模型也天然支持分布式系统。因为 Actor 是最小的并行单元,我们在写代码的时候,可以将整个系统分解成很多 Actor,每个 Actor 是单一职责的,这有点类似面向对象的思想,这样让我们的代码得以解耦。另外,Master 解耦成 Actor 之后,我们可以让这些 Actor 分布在不同的机器上,这样就让 Master 不再成为单点。同时,我们让这些 Actor 根据一致性哈希来进行分配,后续如果有 scheduler 机器挂掉, Actor 可以根据一致性哈希重新分配并重新创建来达到容错的目的。最后,我们的 actors 是跑在多进程上的,每个进程里是很多的协程,这样,我们的 worker 也不会受到 GIL 的限制。像 Scala 或者 Java 这些 JVM 语言 可以使用 akka 这个 Actor 框架,对于 Python 来说,我们并没有什么标准做法,我们认为我们只是需要一个轻量的 Actor 框架就可以满足我们使用,我们不需要 akka 里面一些高阶的功能。因此,我们开发了 Mars actors,一个轻量的 Actor 框架,我们 Mars 整个分布式的 schedulers 和 workers 都在 Mars actors 层之上。这是我们 Mars actors 的架构图,在启动 Actor pool 的时候,我们子进程会根据并发启动若干子进程。主进程上有 socket handler 来接受远程 socket 连接传递消息,另外主进程有个 Dispatcher 对象,用来根据消息的目的地来进行分发。我们所有的 Actor 都在子进程上创建,当 Actor 收到一个消息处理时,我们会通过协程调用 Actor.on_receive(message) 方法。一个 Actor 发送消息到另一个 Actor,分三种情况。它们在同一个进程,那么直接通过协程调用即可。它们在一台机器不同进程,这个消息会被序列化通过管道送到主进程的 Dispatcher,dispatcher 通过解开二进制的头部信息得到目标的进程 ID,通过对应的管道送到对应子进程,子进程通过协程触发相应 Actor 的消息处理即可。它们在不同机器,那么当前子进程会通过 socket 把序列化的消息发送到对应机器的主进程,该机器再通过 Dispatcher 把消息送到对应子进程。由于使用协程作为子进程内的并行方式,而协程本身在 IO 处理上有很强的性能,所以,我们的 Actor 框架在 IO 方面也会有很好的性能。上图是裸用 Mars actors 来求解蒙特卡洛方法算 pi。这里定义两个 Actor,一个 Actor 是 ChunkInside,它接受一个 chunk 的大小,来计算落在圆内点的个数;另外一个 Actor 是 PiCaculator,它负责接受总的点个数,来创建 ChunkInside,这个例子就是直接创建 1000 个 ChunkInside,然后通过发送消息来触发他们计算。create_actor 时指定 address 可以让 Actor 分配在不同的机器上。这里可以看到,我们裸用 Mars actors 的性能是要快过多进程版本的。这里我们总结一下,通过使用 Mars actors,我们能不受 GIL 限制,编写分布式代码变得非常容易,它让我们 IO 变得高效,此外,因为 Actor 解耦,代码也变得更容易维护。现在让我们看下 Mars 分布式的完整执行过程。现在有1个 client,3个 scheduler 和 5个worker。用户创建一个 session,在服务端会创建一个 SessionActor 对象,通过一致性哈希,分配到 scheduler1 上。此时,用户运行了一个 tensor,首先 SessionActor 会创建一个 GraphActor,它会 tile 粗粒度图,图上假设有三个节点,则会创建三个 OperandActor,分别分配到不同的 scheduler 上。每个 OperandActor 会控制 operand 的提交、任务状态的监督和内存的释放等操作。此时 1 和 2 的 OperandActor 发现没有依赖,并且集群资源充足,那么他们会把任务提交到相应的 worker 执行,在执行完成后,向 3 通知任务完成,3 发现 1和2 都执行完成后,因为数据在不同 worker 执行,决定好执行 worker 后,先触发数据拉取操作,然后再执行。客户端这边,通过轮询 GraphActor 得知任务完成,则会触发数据拉取到本地的操作。整个任务就完成了。我们对 Mars 分布式做了两个 benchmark,第一个是对 36 亿数据的每个元素加一再乘以2,图中红色叉是 numpy 的执行时间,可以看到,我们比 numpy 有数倍提升,蓝色的虚线是理论运行时间,可以看到我们真实加速非常接近理论时间加速。第二个 benchmark,我们增加了数据量,来到 144 亿数据,对每个元素加1乘以2后,再求和,可以看到单机 numpy 已经不能完成任务了,此时,针对这个任务,我们也可以取得不错的加速比。未来计划Mars 已经在 Github 上源代码,让更多同学来一起参与共建 Mars:https://github.com/mars-project/mars 。在后续 Mars 的开发计划上,如上文说,我们会支持 eager mode,让每一步触发执行,提升对性能不敏感的任务开发以及 debug 时的使用体验;我们会支持更多 numpy 和 scipy 接口;后续很重要的一个是,我们会提供 100% 兼容 pandas 的接口,由于利用了 mars tensor 作为基础,我们也可以提供 GPU 的支持;我们会提供兼容 scikit-learn 的机器学习的支持;我们还会提供在细粒度图上调度自定义函数和自定义类的功能,增强灵活性;最后,因为我们客户端其实并不依赖 Python,任意语言都可以序列化粗粒度图,所以我们完全可以提供多语言的客户端版本,不过这点,我们会视需求而定。总之,开源对我们是很重要的,庞大的 scipy 技术栈的并行化,光靠我们的力量是不够的,需要大家来一起帮我们来共建。现场图片最后再 po 一点现场图片吧,现场观众对 Mars 的问题还是蛮多的。我大致总结下:Mars 在一些特定计算的性能,比如 SVD 分解,这里我们有和用户合作项目的一些测试数据,输入数据是 8亿*32的矩阵做 SVD 分解,分解完再矩阵乘起来和原矩阵做对比,这整个计算过程使用 100个 worker(8核),用7分钟时间算完Mars 何时开源,我们已经开源:https://github.com/mars-project/marsMars 开源后会不会闭源,答:不会Mars actors 的详细工作原理Mars 是静态图还是动态图,目前是静态图,eager mode 做完后可以支持动态图Mars 会不会涉及深度学习,答:目前不会本文作者:继盛阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 10, 2019 · 3 min · jiezi

Mars 算法实践——人脸识别

Mars 是一个基于矩阵的统一分布式计算框架,在之前的文章中已经介绍了 Mars 是什么, 以及 Mars 分布式执行 ,而且 Mars 已经在 GitHub 中开源。当你看完 Mars 的介绍可能会问它能做什么,这几乎取决于你想做什么,因为 Mars 作为底层运算库,实现了 numpy 70% 的常用接口。这篇文章将会介绍如何使用 Mars 完成你想做的事情。奇异值分解 (SVD)在处理纷繁的数据时,作为数据处理者,首先想到的就是降维,SVD 就是其中一种比较常见的降维方法,在 numpy.linalg 模块中就有 svd 方法,当我们有20000个100维的数据需要处理,调用 SVD 接口:In [1]: import numpy as npIn [2]: a = np.random.rand(20000, 100)In [3]: %time U, s, V = np.linalg.svd(a)CPU times: user 4min 3s, sys: 10.2 s, total: 4min 13sWall time: 1min 18s可以看到即使 Numpy 使用了 mkl 加速,也需要1分多钟的运行时间,当数据量更大时,单机的内存已经无法处理。Mars 也实现了 SVD ,但是它比 Numpy 有更快的速度,因为利用矩阵分块计算的算法,能够并行计算:In [1]: import mars.tensor as mtIn [2]: a = mt.random.rand(20000, 100, chunk_size=100)In [3]: %time U, s, V = mt.linalg.svd(a).execute()CPU times: user 5.42 s, sys: 1.49 s, total: 6.91 sWall time: 1.87 s可以看到在相同数据量情况下,Mars 有几十倍速度的提升,仅仅需要1秒多钟就可以解决20000数据量的降维问题。想象一下淘宝用户数据做矩阵分解时,分布式的矩阵运算就显现出其价值。主成分分析 (PCA)提到降维,主成分分析也是一种重要的手段。PCA 会选取包含信息量最多的方向对数据进行投影,其投影方向可以从最大化方差或者最小化投影误差两个角度理解。也就是通过低维表征的向量和特征向量矩阵,可以基本重构出所对应的原始高维向量。其最主要的公式如下所示:xi为每个样本的数据,j为新的投影方向,我们的目标就是使得投影方差最大化,从而找到主特征。上面式子中的矩阵C在数学中可以用协方差矩阵表示,当然首先要对输入的样本做中心化调整。我们可以用随机产生的数组看一下 Numpy 是如何实现 PCA 降维操作:import numpy as npa = np.random.randint(0, 256, size=(10000, 100))a_mean = a.mean(axis=1, keepdims=True)a_new = a - a_meancov_a = (a_new.dot(a_new.T)) / (a.shape[1] - 1)#利用SVD求协方差矩阵前20个特征值U, s, V = np.linalg.svd(cov_a)V = V.Tvecs = V[:, :20]#用低纬度的特征向量表示原数据a_transformed = a.dot(vecs)由于随机产生的数据本身就没有太强的特征,所以在100维数据中象征性的取出前20维,一般可以用特征值的比例取总和的前99%之类的数值。再看一下 Mars 是如何实现的:import mars.tensor as mta = mt.random.randint(0, 256, size=(10000, 100))a_mean = a.mean(axis=1, keepdims=True)a_new = a - a_meancov_a = (a_new.dot(a_new.T)) / (a.shape[1] - 1)#利用SVD求协方差矩阵前20个特征值U, s, V = mt.linalg.svd(cov_a)V = V.Tvecs = V[:, :20]#用低纬度的特征向量表示原数据a_transformed = a.dot(vecs).execute()可以看到除了 import 的不同,再者就是对最后需要数据的变量调用 execute 方法,甚至在未来我们做完 eager 模式后, execute 都可以省去,以前用 Numpy 写的算法可以几乎无缝转化成多进程以及分布式的程序,再也不用自己手动去写MapReduce。人脸识别当 Mars 实现了基础算法时,便可以使用到实际的算法场景中。PCA最著名的应用就是人脸特征提取以及人脸识别,单个人脸图片的维度很大,分类器很难处理,早起比较知名的人脸识别 Eigenface 算法就是采用PCA算法。本文以一个简单的人脸识别程序作为例子,看看 Mars 是如何实现该算法的。本文的人脸数据库用的是ORL face database,有40个不同的人共400张人脸图片,每张图片为 92112 像素的灰度图片。这里选取每组图片的第一张人脸图片作为测试图片,其余九张图片作为训练集。首先利用 python 的 OpenCV 的库将所有图片读取成一个大矩阵,也就是 36010304大小的矩阵,每一行是每个人脸的灰度值,一共有360张训练样本。利用 PCA 训练数据,data_mat 就是输入的矩阵,k 是需要保留的维度。import mars.tensor as mtfrom mars.session import new_sessionsession = new_session()def cov(x): x_new = x - x.mean(axis=1, keepdims=True) return x_new.dot(x_new.T) / (x_new.shape[1] - 1)def pca_compress(data_mat, k): data_mean = mt.mean(data_mat, axis=0, keepdims=True) data_new = data_mat - data_mean cov_data = cov(data_new) U, s, V = mt.linalg.svd(cov_data) V = V.T vecs = V[:, :k] data_transformed = vecs.T.dot(data_new) return session.run(data_transformed, data_mean, vecs)由于后续做预测识别,所以除了转化成低维度的数据,还需要返回平均值以及低维度空间向量。可以看到中间过程平均脸的样子,前几年比较火的各地的平均脸就可以通过这种方式获取,当然这里的维度以及样本比较少,大概只能看出个人脸的样子。其实 data_transformed 中保存的特征脸按照像素排列之后也能看出特征脸的形状。图中有15个特征脸,足以用来做一个人脸分类器。另外在函数 PCA 中用了 session.run 这个函数,这是由于三个需要返回的结果并不是相互独立的,目前的延迟执行模式下提交三次运算会增加运算量,同一次提交则不会,当然立即执行模式以及运算过的部分图的剪枝工作我们也在进行中。当训练完成之后,就可以利用降维后的数据做人脸识别了。将之前非训练样本的图片输入,转化成降维后的维度表示,在这里我们就用简单的欧式距离判断与之前训练样本中每个人脸数据的差距,距离最小的就是识别出的人脸,当然也可以设置某个阈值,最小值超过阈值的判断为识别失败。最终在这个数据集下跑出来的准确率为 92.5%,意味着一个简单的人脸识别算法搭建完成。# 计算欧氏距离def compare(vec1, vec2): distance = mt.dot(vec1, vec2) / (mt.linalg.norm(vec1) * mt.linalg.norm(vec2)) return distance.execute()未来上文展示了如何利用 Mars 一步一步地完成人脸识别小算法的过程,可以看到 Mars 类 Numpy 的接口对算法开发人员十分友好,算法规模超出单机能力时,不再需要关注如果扩展到分布式环境,Mars 帮你处理背后所有的并行逻辑。当然,Mars 还有很多可以改进的地方,比如在 PCA 中对协方差矩阵的分解,可以用特征值、特征向量计算,计算量会远小于 SVD 方法,不过目前线性代数模块还没有实现计算特征向量的方法,这些特性我们会一步步完善,包括 SciPy 里各种上层算法接口的实现。大家有需求的可以在 GitHub 上提 issue 或者帮助我们共建 Mars。Mars 作为一个刚刚开源的项目,十分欢迎提出其他任何想法与建议,我们需要大家的加入,让 Mars 越来越好。本文作者:继盛阅读原文本文为云栖社区原创内容,未经允许不得转载。 ...

January 9, 2019 · 2 min · jiezi