Python类库学习
# 基础语法
# Numpy学习
# Ndarray类学习
点击查看
# NumPy 参考手册 https://www.numpy.org.cn/reference/
"""Ndarray类学习 (存放同类型元素的多维数组)"""
import numpy as np
"""
ndarray.ndim - 数组的轴(维度)的个数。在Python世界中,维度的数量被称为rank。
ndarray.shape - 数组的维度。这是一个整数的元组,表示每个维度中数组的大小。对于有 n 行和 m 列的矩阵,shape 将是 (n,m)。因此,shape 元组的长度就是rank或维度的个数 ndim。
ndarray.size - 数组元素的总数。这等于 shape 的元素的乘积。
ndarray.dtype - 一个描述数组中元素类型的对象。可以使用标准的Python类型创建或指定dtype。另外NumPy提供它自己的类型。例如numpy.int32、numpy.int16和numpy.float64。
ndarray.itemsize - 数组中每个元素的字节大小。例如,元素为 float64 类型的数组的 itemsize 为8(=64/8),而 complex32 类型的数组的 itemsize 为4(=32/8)。它等于 ndarray.dtype.itemsize 。
ndarray.data - 该缓冲区包含数组的实际元素。通常,我们不需要使用此属性,因为我们将使用索引访问数组中的元素
"""
# order="C" 行优先
# arr1 = np.ndarray(shape=(2, 3), dtype = int, buffer=np.array([1,2,3,4,5,6,7]), offset=0, order="C")
# arr1
# order="F" 列优先
# arr2 = np.ndarray(shape=(2, 3), dtype = int, buffer=np.array([1,2,3,4,5,6,7]), offset=0, order="F")
# arr2
# offset=8 buffer中用于初始化数组的首个数据的偏移 (字节数的偏移 ndarray.itemsize为4 设置为8偏移两个值)
arr3 = np.ndarray(shape=(2, 3), dtype = int, buffer=np.array([1,2,3,4,5,6,7,8]), offset=8, order="C")
# arr3.itemsize
arr3
# np.array方法
点击查看
"""
np.array只是一个便捷的函数,用来创建ndarray,
它本身并不是一个类
"""
from numpy import *
arr4 = array(range(15)).reshape(3, 5)
# arr4
# print(arr4.T)
# print(arr4.size)
# print(arr4.itemsize)
# print(arr4.ndim)
# print(arr4.shape)
# print(arr4.dtype)
"""通过常规类型创建array"""
# 1.通过tuple创建array
# yuanzu = (4, 5, 6)
# arr5 = array(yuanzu)
# print(arr5)
# 2.通过list创建array
# pylist = [0, 1, 2]
# arr6 = array(pylist)
# print(arr6)
# 3.构建多维的array
# pylist2 = [4, 5, 6]
# arr7 = array( [pylist, pylist2] )
# print("多维数组:\n" + str(arr7))
# 4.类型自动推断
# arr8 = array( [1, 2, 3.3] )
# print(arr8)
# arr8 = array( ["1", 2, 3] )
# print(arr8)
# 5.明确数组类型
# arr9 = array([1, 3, 6, 9], dtype=float32)
# arr9
arr9 = array(['1', 3, 6, 9], dtype=ubyte)
arr9
# Numpy数组创建方法
点击查看
"""Numpy数组创建方法"""
# from numpy import *
# 1. 全0数组
# arr = zeros( (3, 4) ) # 二维全0数组
# arr = zeros( (2,2,2) ) # 三维全0数组
# 1.1 全1数组
# arr = ones( (2, 3) )
# 1.2 初始内容是随机的,取决于内存的状态
arr = empty( (2, 3) )
# 1.2 全x数组
# arr = full( (2, 3), 6 )
# 1.3 根据步长创建数组arange(start, end, step)
# arr = arange(0, 1, 0.1)
# 2.等差数列
# arr = linspace(0, 1, 10) # linspace(start, end, count, endpoint=True)
# arr = linspace(0, 1, 10, endpoint=False)
# 3.等比数列
# arr = logspace(0, 10, 1, base=2) # logspace(start, end, count, base=10)
arr
# 打印数组
点击查看
"""打印数组"""
# import sys
# 一维数组打印为行,将二维数据打印为矩阵,将三维数据打印为矩数组表
# arr = arange(10000)
# 如果数组太大而无法打印,NumPy会自动跳过数组的中心部分并仅打印角点
# arr.reshape(100, 100)
# 禁用此行为并强制NumPy打印整个数组 更改打印选项set_printoptions
# set_printoptions(threshold=sys.maxsize)
# arr.reshape(100, 100)
# 基本操作 (数组元素的运算)
点击查看
"""基本操作 (数组元素的运算)"""
import numpy as np
a = np.array([10, 20, 30, 40, 50])
b = np.array(np.arange(5))
print("%s%s" % ("数组a-数组b:\t",a - b)) # 数组相减
print("%s%s" % ("数组b的2次方:\t",b**2))
print("%s%s" % ("sin(a):\t", np.sin(a)))
print("%s%s" % ("数组a < 35\t",a < 35))
# 基本操作 (矩阵乘积)
点击查看
"""基本操作 (矩阵乘积)"""
A = np.array( [[1,1], [0,1]] )
B = np.array( [[2,0], [3,4]] )
print("矩阵乘积:" + str(A @ B))
print("矩阵乘积:" + str(A.dot(B)))
"""
某些操作(例如+=和 *=)会更直接更改被操作的矩阵数组而不会创建新矩阵数组
"""
A *= 0
A += 3
B = np.random.random( (2, 2) )
print(B)
# A += B # 需要向上转换 TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int32') with casting rule 'same_kind'
B += A
print("B += A:\n" + str(B))
"""一元操作"""
# B.sum() # 所有元素的和
# B.min() # 最小的元素
# B.max() # 最大的元素
# B.sum(axis=0) # sum of each column
# B.min(axis=1) # min of each row
# B.cumsum(axis=1) # 在每一行的累积 cumulative sum along each row
"""
通函数
NumPy提供熟悉的数学函数,例如sin,cos和exp。在NumPy中,这些被称为“通函数”(ufunc)。在NumPy中,这些函数在数组上按元素进行运算,产生一个数组作为输出
"""
# 形状操纵
点击查看
"""形状操纵 0428"""
import numpy as np
# 改变数组的形状
arr = np.floor(np.random.random( (3,4) ) * 10)
print(arr.shape)
print(arr)
# arr.ravel() # returns the array, flattened
# arr.T
# arr.reshape(6, -2)
# 将不同数组堆叠在一起
arr1 = np.array([ [[1,2], [3,4]], [[5,6], [7,8]] ])
arr2 = np.array([ [[10,20], [30,40]], [[50,60], [70,80]] ])
# np.vstack( (arr1, arr2) ) # 沿第一轴[水平(按列顺序)]堆叠
# np.row_stack( (arr1, arr2) )
# np.hstack( (arr1, arr2) ) # 沿第二轴[垂直(按照行顺序)]堆叠
# np.column_stack( (arr1, arr2) )
## 在复杂的情况下,r_和 c_于通过沿一个轴堆叠数字来创建数组很有用。它们允许使用范围操作符(“:”)。
# np.r_[1:6, 0, 4]
# np.r_[arr1, arr2]
# np.c_[arr1, arr2]
# 复制堆叠 numpy.repeat(a, repeats, axis=None)
# '''
# a(array_like): 输入数组。
# repeats(int or array of ints): 每个元素的重复次数。 重复播放以适合给定轴的形状
# axis(int, optional) 重复值所沿的轴。默认情况下,使用展平的输入数组,并返回展平的输出数组。
# '''
# np.repeat(a=3, repeats=4)
# np.repeat(a=arr1, repeats=2)
# np.repeat(a=arr1, repeats=2, axis=2)
# '''title'''
# 将一个数组拆分成几个较小的数组
# np.hsplit(arr1, (2,2))
# a = np.array([np.arange(1,13), np.arange(1,13)*10])
# np.hsplit(a, 3) # 无论数组尺寸如何,数组始终沿第二轴分割
# np.hsplit(a, (3, 6, 9)) # (第二个参数是切分的块??? 012 345 678 9-)
# np.vsplit(a, 2) # 该阵列被始终沿第一轴线分裂不管阵列的尺寸
# '''split split(array, splits,axis=1) 将数组拆分为大小相等的多个子数组
# numpy.array_split(ary,indexs_or_sections,axis = 0 )
# array_split允许 indices_or_sections是整数,它不平分轴。对于应分为n个部分的长度为l的数组,它返回大小为l // n + 1的l%n个子数组,其余大小为l // n
# '''
# np.array_split(ary=arr1, indices_or_sections=2, axis= 2)
arr3 = np.array([arr, arr*10])
print("arr3:\n" + str(arr3))
# np.split(ary=arr3, indices_or_sections=arr3.shape[0], axis=0)
# 索引、切片和迭代
点击查看
import numpy as np
"""索引、切片和迭代"""
'''
一维的数组可以进行索引、切片和迭代操作的,就像 列表 和其他Python序列类型一样。
'''
arr = np.arange(12)**3
print(arr[5]) # 索引
print(arr[0:12:2]) # 切片
# 迭代
for i in arr:
print(i, end=" ")
'''
多维的数组每个轴可以有一个索引。这些索引以逗号分隔的元组给出:
'''
arr = arr.reshape( (3,4) )
print("第三行第一个元素:" + str(arr[2, 0])) # 索引
# -1对应二维数组里的一维说的,但不包含最后一个一维数组;-2对应一维数组里的元素,不包含每个一维数组最后两个
print(arr[:-1,:-2]) # 切片
# 迭代
for elem in arr.flat:
print(elem, end=" ")
arr
# 深入:
点击查看
"""拷贝和视图"""
# 完全不复制
# 视图或浅拷贝
# 深拷贝
"""Less基础 广播(Broadcasting)规则"""
"""花式索引和索引技巧"""
# 使用索引数组进行索引
# 使用布尔数组进行索引
import numpy as np
import matplotlib.pyplot as plt
def mandelbrot( h,w, maxit=20 ):
"""用布尔索引生成Mandelbrot集的图像:"""
"""Returns an image of the Mandelbrot fractal of size (h,w)."""
y,x = np.ogrid[ -1.4:1.4:h*1j, -2:0.8:w*1j ]
c = x+y*1j
z = c
divtime = maxit + np.zeros(z.shape, dtype=int)
for i in range(maxit):
z = z**2 + c
diverge = z*np.conj(z) > 2**2 # who is diverging
div_now = diverge & (divtime==maxit) # who is diverging now
divtime[div_now] = i # note when
z[diverge] = 2 # avoid diverging too much
return divtime
plt.imshow(mandelbrot(400,400))
plt.show()
# ix_()函数
# 使用字符串建立索引
"""线性代数 简单数组操作"""
"""“自动”整形"""
"""矢量堆叠"""
# 深入: 直方图
点击查看
"""直方图"""
import numpy as np
import matplotlib.pyplot as plt
# Build a vector of 10000 normal deviates with variance 0.5^2 and mean 2
mu, sigma = 2, 0.5
v = np.random.normal(mu,sigma,10000)
# Plot a normalized histogram with 50 bins
plt.hist(v, bins=50, density=1) # matplotlib version (plot)
plt.show()
# Compute the histogram with numpy and then plot it
(n, bins) = np.histogram(v, bins=50, density=True) # NumPy version (no plot)
plt.plot(.5*(bins[1:]+bins[:-1]), n)
plt.show()
# 附:创建一个3*3 的数组方法
点击查看
import numpy as np
# 创建一个3*3 的数组, 下列代码错误的是
# A:np.arange(9).reshape(3,3)
# B:np.eye(3)
# C:np.random.random([3,3,3])
# D:np.mat("1 2 3;4 5 6;7 8 9")
# 正确答案:C
# arr = np.arange(9).reshape(3,3)
# arr = np.eye(3) # 生成对角矩阵
arr = np.random.random([3,3,3])
# arr = np.mat("1 2 3;4 5 6;7 8 9")
print(arr.shape)
arr
# Pandas(两种数据结构学习)
# 1.Series(一维标记数组)学习
点击查看
"""pandas 简介:https://www.pypandas.cn/docs/getting_started/ """
import pandas as pd
import numpy as np
"""Series(一维标记数组)学习"""
# obj = pd.Series([1, 3, 5, np.nan, 6, "ai"]) # 默认下标0123
obj = pd.Series([1, 2, 3, 4, 5], index=['d', 'b', 'a', 'c', 'e'])
# obj
# obj.values # 返回Series的值 为ndarray类型
# obj.index # 返回索引名称
'''series索引'''
# 1.类似numpy索引方式
# obj[2:6:2]
# 2.index名称索引
# obj["a"] # 单个
# obj[ ["a", "d", "e"] ] # 索引多个值,需要传入名称列表
# obj["a":"c"] # 包括"c"
# 3.通过布尔表达式索引
# obj[obj>=3]
'''series赋值'''
# 1.单个值赋值
# obj[2] = 9
# 2.多个值赋值
# obj[0:2] = [-9, -6]
# 3.通过布尔表达式赋值
obj[obj<3] = 0
obj
# 2.DataFrame(二维标记数据结构)学习
# 创建
点击查看
import pandas as pd
import numpy as np
"""
DataFrame( data, index, columns, dtype, copy)(二维标记数据结构)学习
1. 像Series一样可以接收多种输入:lists、dicts、series和DataFrame等
2.初始化对象时,除了数据还可以传index和columns这两个参数
附:可以把DataFrame想象成一个电子表格,它由行名(index)、列名(columns)和数据(values)组成。
"""
# 1.根据字典新建DataFrame
# data = {
# 'column_a':[1, 2, 3],
# 'column_b':[4, 5, 6],
# 'column_c':[7, 8, 9]
# }
# df = pd.DataFrame(data, index=['r1', 'r2', 'r3'])
# 1.2.根据嵌套字典新建DataFrame
# data = {
# 'c1':{'r1':111, 'r2':122},
# 'c2':{'r1':211, 'r2':222}
# }
# df = pd.DataFrame(data)
# 2. 根据列表创建DataFrame
# data = [
# [1111, 2222, 3333],
# [111, 222, 333],
# [11, 22, 33],
# [1, 2, 3]
# ]
# df = pd.DataFrame(data, columns=['c1', 'c2', 'c3'], index=['r1', 'r2', 'r3', 'r4'])
# 3. DataFrame 和 ndarray 互操作
# 3.1 用ndarray构造DataFrame
narr = np.array([
[11, 22, 33, 44, 55],
[1.1, 2.2, 3.3, 4.4, 5.5]
])
df = pd.DataFrame(narr, columns=['c1', 'c2', 'c3', 'c4', 'c5'], index=['r1', 'r2'])
# 3.2 用DataFrame构造ndarray
## narr2 = np.array(df)
# narr2 = df.values
# print(narr2)
### end.输出
# print(df.index)
# print(df.columns)
# print(df.values) # 返回值为ndarray类型
# print(df.values.shape)
# print(df.index.shape)
df
# DataFrame值索引
点击查看
import pandas as pd
import numpy as np
"""DataFrame值索引"""
data = [
[1111, 2222, 3333],
[111, 222, 333],
[11, 22, 33],
[1, 2, 3]
]
df = pd.DataFrame(data, columns=['c1', 'c2', 'c3'], index=['r1', 'r2', 'r3', 'r4'])
# 1.列索引(DataFrame[column_name],返回对应列的所有值)
# df['c1']
# 2. 行索引(DataFrame.ix[index_name],返回对应行的所有值。返回值类型为Series。)
# df.ix['r1'] # 注意这里是中括号,不是函数??? (被弃用????)
# 3.DataFrame.loc[index_name,column_name],返回对应元素。
# df.loc['r1'] # 行索引
# df.loc[:, 'c1'] # 列索引
# df.loc['r1', 'c1']
# df.loc[ ['r1', 'r3'] ] # 返回值为DataFrame。
# df.loc['r1': 'r3', 'c2'] # 切片 包括起始和结束
# df.loc[ df['c1']>100, ['c2'] ] # 有条件的返回布尔序列 + 指定列
# df[df>100] # bool值的索引方法
# 3.1 设定值 (实质上是给索引赋值??)
# df.loc[df['c1']>100, ['c2'] ] = 2000
# df
# 4.DataFrame.iloc[x,y],返回对应元素。
# 参数(整数 # df.iloc[0] # 整数 具有整数的切片对象,例如1:7 布尔数组 一个callable带有一个参数的函数(调用Series或DataFrame))
# df.iloc[0] # 整数
# df.iloc[ [0, 1] ] # df.iloc[0] # 整数
# df.iloc[ 0:3:2 ] # 切片对象
# df.iloc[[True, False, True, True]] # 布尔掩码与索引的长度相同
# df = pd.DataFrame(data, columns=['c1', 'c2', 'c3'])
# df.iloc[lambda x: x.index % 2 == 0]
# 层次化索引与unstack
点击查看
"""层次化索引与unstack"""
"""
层次化索引可以在一个轴上拥有多个索引级别。也就是以低维度形式处理高维度数据。
unstack()函数可以将层次化series转换成高维的DataFrame。
"""
import pandas as pd
import numpy as np
data = pd.Series(np.random.randn(10), index=[['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'd', 'd'], [1, 2, 3, 1, 2, 3, 1, 2, 2, 3]])
# data # 两层索引
data.unstack()
# DataFrame堆叠
点击查看
"""DataFrame堆叠 (shape相同) [DataFrame表有行和列标签,因此堆叠时shape可以不一致]"""
import numpy as np
import pandas as pd
df = pd.DataFrame(np.array([[1,2,3],[4,5,6]]), index=['Ⅰ', 'Ⅱ'])
df2 = pd.DataFrame(np.array([[10,20,30],[40,50,60]]), index=['Ⅰ', 'Ⅱ'])
# concat([pd1,pd2],axis=0,ignore_index=False)
# print( pd.concat([df, df2]) )
# pd.concat([df, df2], ignore_index=False) # 纵向堆叠时,忽略索引名
pd.concat([df, df2], axis=1)# 横向堆叠
# frame = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
# print('值排序1 :\n', frame.sort_index(by='b', axis=0))
# frame
# DataFrame常用函数介绍(一) 重新索引(reindex)
点击查看
"""DataFrame常用函数介绍(一) 重新索引(reindex)"""
"""
参数DataFrame.reindex(self,
labels=None, index=None, columns=None, axis=None,
method=None, copy=True, level=None, fill_value=nan, limit=None, tolerance=None)
"""
import pandas as pd
df = pd.DataFrame(np.array([[1,2,3],[4,5,6]]), index=['Ⅰ', 'Ⅱ'], columns=['a', 'b', 'c'])
df.reindex(index=['Ⅰ', 'Ⅱ', 'Ⅲ'], columns=['a', 'b', 'c', 'd'], fill_value=0 )
# DataFrame常用函数介绍(二) 丢弃值(drop)
点击查看
"""DataFrame常用函数介绍(二) 丢弃值(drop) [Ⅰ, Ⅱ, Ⅲ, Ⅳ, Ⅴ, Ⅵ, Ⅶ, Ⅷ, Ⅸ, Ⅹ]"""
"""
参数DataFrame.drop(self, labels=None, axis=0, index=None,
columns=None, level=None, inplace=False, errors='raise')
"""
import pandas as pd
import numpy as np
df = pd.DataFrame(np.array([[1,2,3],[4,5,6], [7,8,9], [np.nan,10,np.nan]]),
index=['Ⅰ', 'Ⅱ', 'Ⅲ', 'Ⅳ'], columns=['a', 'b', 'c'])
# df.drop(index='Ⅲ', axis=0) # 删除行 (返回新对象)
# df.drop(columns='b', axis=1) # 删除列 (返回新对象)
# 参数 DataFrame.dropna(self, axis=0, how='any', thresh=None, subset=None, inplace=False)
# df.dropna() # 清除有空值(NaN)的行
df.dropna(how='all') # 清除全为空的行(axis=1的列)
df.dropna(subset=['列名'],inplace=True) # 某列为空删除这一行
# df
# DataFrame常用函数介绍(三) 算术方法
点击查看
"""DataFrame常用函数介绍(三) 算术方法"""
"""
参数:add(self, other, axis='columns', level=None, fill_value=None)
sub(self, other, axis='columns', level=None, fill_value=None)
div(self, other, axis='columns', level=None, fill_value=None)
sub(self, other, axis='columns', level=None, fill_value=None)
"""
import numpy as np
import pandas as pd
df = pd.DataFrame(np.arange(4).reshape((2,2)), columns=list('ab'))
df2 = pd.DataFrame(np.arange(6).reshape((2,3)), columns=('Ⅰ', 'Ⅱ', 'Ⅲ'))
# df + df2
# df.add(df2)
df.add(10)
# DataFrame常用函数介绍(四) 索引排序
点击查看
"""DataFrame常用函数介绍(四) 索引排序"""
"""
DataFrame.sort_index(self, axis=0, level=None, ascending=True, inplace=False,
kind='quicksort', na_position='last', sort_remaining=True, ignore_index: bool = False)
"""
import pandas as pd
import numpy as np
df = pd.DataFrame(np.array([[1,2,3], [7,8,9], [4,5,6], [np.nan,5.5,np.nan]]),
index=['Ⅲ', 'Ⅳ', 'Ⅰ', 'Ⅱ'], columns=['b', 'a', 'c'])
# print(df)
# df.sort_index() # 按索引排序
# df.sort_index(by=['a', 'b']) # 不推荐使用sort_index的参数,请使用.sort_values(by = ...)
# df.sort_index(axis = 1, ascending=False) # 按照列索引名降序排序
df.sort_index(axis = 0, ascending=False)
# df.sort_values(by=[ 'a']) # 按值排序
# DataFrame常用函数介绍(五) 描述和汇总统计(待补充)
点击查看
"""DataFrame常用函数介绍(五) 描述和汇总统计(补充)"""
import pandas as pd
df = pd.DataFrame({'b': [4, 7, -3, 2], 'a': [0, 1, 0, 1]})
df.cov() # 协方差计算方法,series需要通过参数传入
df.corr() # 相关系数计算方法,series需要通过参数传入
# DataFrame常用函数介绍(六) 缺失值填充
点击查看
"""DataFrame常用函数介绍(六) 缺失值填充"""
import pandas as pd
import numpy as np
df = pd.DataFrame(np.array([[1,2,3], [7,8,9], [4,5,6], [np.nan,5.5,np.nan]]),
index=['Ⅲ', 'Ⅳ', 'Ⅰ', 'Ⅱ'], columns=['b', 'a', 'c'])
# print(df)
# df.fillna(0) # 全填为0
# df.fillna({'b':666, 'c':999}) # 参数为字典类型 不同列填充不同值
df.fillna(df.mean()) # 列平均值填充列对应的NaN值
# Pandas文件读取
点击查看
"""文件读取"""
import pandas as pd
# filepath = 'data\music.csv'
filepath = 'data\sales-副本.csv' # 含中文的文件 65行
# 1.read_csv方法
df = pd.read_csv(filepath,
encoding='gbk',
names=['发票id', '销售日期', '总金额', '支付金额', '收银员'], # 指定列名,不使用第一行作为列名
skiprows=[0], # 忽略指定列
# na_values=['NULL'], # 显示空值
# nrows=12, # 文件大时 设置读取行
# chunksize=4 # 每次读取4行
)
# 1.1使用chunksize=4参数,读取后的数据类型为TextFileReader
# for ele in df:
# print(ele)
# 2.read_table方法
# df = pd.read_table(filepath, sep=',', encoding='gbk')
# print("Dataframe的形状" + str(df.shape))
df
# df.fillna("空值")
# Pandas文件写入
点击查看
"""文件写入"""
import pandas as pd
import numpy as np
# import sys
df = pd.DataFrame([
['NaN', 88, 66, 55, 39],
[53, 52, 86, 66, np.nan],
[21, 98, 68, 'NULL', 99]
])
# df
filepath = 'data\pfile_test.csv'
df.to_csv(filepath, # sys.stdout, # 输出到控制台
na_rep='non', # 存储空值
sep='\t', # 设置分隔符
index=False, # 不存储索引(index)
header=False, # 不存储列名
# columns=[0, 1] # 设置只保存 某些列
)
# Pandas合并xls文件
点击查看
import pandas as pd
import os
file_path = "D:\\software\\pythonProjects\\weibospider\\weibospider\\spiders\\data\\weibo"
file_list = [f"{file_path}" + i for i in os.listdir(file_path)]'
li=[]
for i in file_list:
li.append(pd.read_excel(i))
writer = pd.ExcelWriter(f'{file_path}\微博.xlsx')
pd.concat(li).to_excel(writer,'Sheet1',index=False)
writer.save()
# Pandas数据合并、清洗
# merge函数 默认内连接
点击查看
import pandas as pd
"""merge函数 默认内连接"""
"""1.内连接(默认) how = 'inner'"""
# 1.1 按 相同列名 内连接
# df1 = pd.DataFrame({'key':['b','b','a','c'], 'data1':range(4)})
# df2 = pd.DataFrame({'key':['a','b','d'], 'data2':range(3)})
# df3 = pd.merge(df1, df2, on = 'key', how = 'inner')
# 1.2 没有同名列 (相当于把参数on= 变为 left_on 和 right_on两个参数)
df1 = pd.DataFrame({'key1':['b','b','a','c'], 'data1':range(4)})
df2 = pd.DataFrame({'key2':['a','b','d'], 'data1':range(3)})
df3 = pd.merge(df1, df2, left_on='key1', right_on='key2')
# print(f"{df1}\n{df2}")
df3
# 外连接
# 外连接
点击查看
import pandas as pd
""" 2.外连接 """
''' 1.how 2.多列连接on=[] 3.区分相同列名suffixes= 4.索引名连接right_index=True'''
# 2.1.1 how = 'outer'
df1 = pd.DataFrame({'key': ['b', 'b', 'a', 'c'],'data1': range(4)})
df2 = pd.DataFrame({'key': ['a', 'b', 'd'],'data2': range(3)})
df3 = pd.merge(df1,df2,how='outer')
# print(f"{df1}\n{df2}")
df3
# 多列连接on=[]
点击查看
import pandas as pd
# 2.1.2 多列连接on=[]
df1 = pd.DataFrame({'k1': ['A', 'A', 'B'], 'k2': ['a', 'b', 'a'], 'lval': [1, 2, 3]})
df2 = pd.DataFrame({'k1': ['A', 'A', 'B', 'B'], 'k2': ['a', 'a', 'a', 'b'], 'rval': [4, 5, 6, 7]})
df3 = pd.merge(df1, df2, how='outer',on= ['k1', 'k2'])
# 2.1.3 非连接列有重名时指定后缀
# df3 = pd.merge(df1, df2, how='outer',on='k1', suffixes=['_x', '_y'])
# print(f"{df1}\n{df2}")
df3
# 左连接 how = 'left'
点击查看
import pandas as pd
# 2.2
df1 = pd.DataFrame({'key':['b','b','a','c'], 'data1':range(4)})
df2 = pd.DataFrame({'key':['a','b','d'], 'data2':range(3)})
# 2.2 左连接 how = 'left'
df3 = pd.merge(df1, df2, on = 'key', how = 'left')
# print(f"{df1}\n{df2}")
df3
# how = 'right'
点击查看
import pandas as pd
# 2.2
df1 = pd.DataFrame({'key':['b','b','a','c'], 'data1':range(4)})
df2 = pd.DataFrame({'key':['a','b','d'], 'data2':range(3)})
# 2.3 右连接 how = 'right'
df3 = pd.merge(df1, df2, on = 'key', how = 'right')
# print(f"{df1}\n{df2}")
df3
# 用表的行索引名作为连接
点击查看
import pandas as pd
# 2.4.1 用表的行索引名作为连接
df1 = pd.DataFrame({'key': ['a', 'b', 'a', 'c'],'value': range(4)})
df2 = pd.DataFrame({'val': [4, 9]}, index=['a', 'b'])
df3 = pd.merge(df1, df2, left_on='key', right_index=True, how='outer')
df3 = pd.merge(df1, df2, left_on='key', right_index=True, how='outer')
# print(f"{df1}\n{df2}")
df3
# join函数(为merge的特例) 默认外连接
点击查看
import pandas as pd
"""join函数(为merge的特例) 默认外连接"""
df1 = pd.DataFrame({'key1': ['b', 'b', 'a', 'c'],'data1': range(4)})
df2 = pd.DataFrame({'key2': ['a', 'b', 'd'],'data2': range(3)})
# 两种方式相当
print(pd.merge(df1, df2,left_index=True, right_index=True))
df1.join(df2, how='inner')
# combine_first函数 以一个为基准,另一个进行补充
点击查看
import pandas as pd
import numpy as np
"""combine_first函数 以一个为基准,另一个进行补充"""
df1 = pd.DataFrame(np.arange(6).reshape((2, 3)),index=['a','b'])
df2 = pd.DataFrame(np.arange(6).reshape((3, 2)),index=['a','b','c'])
# 体会两者的区别
print(df1.combine_first(df2)) # df1值为NaN的位置,由df2来填充
df2.combine_first(df1) # 以df2为准,用df1补空
# 待补充
点击查看
"""
pd.concat与np.concatenate对比
pd.concat与pd.merge与join
Concat忽略索引
"""
# 数据清理与转换(一) 值替换
点击查看
"""数据清理与转换(一) 值替换"""
import numpy as np
import pandas as pd
"""数据清理--值替换"""
''' 1. df.fillna()方法[对NaN值进行填充] '''
df = pd.DataFrame([[1,np.nan,2,0], [np.nan, np.nan, np.nan, np.nan,], [3, np.nan,5,6]])
print(df) # 打印原始值
# 1.1 全部填充为0
# df.fillna(0)
# 1.2 填充为列平均值
# df.fillna(df.mean())
# 1.3 不同列采用不同填充
# df.fillna({0:0.0, 1:1.1, 2:2.2, 3:3.3})
'''
2.df.replace()方法,对不同值(比如0, -1, NaN)进行填充
附:df.replace(np.nan, 0) 相当于 df.fillna(0)
'''
# 2.1 把多个值[np.nan, 0] 替换为 -1
# df.replace([np.nan, 0], -1)
# 2.2 把多个值 替换为 多个值
df.replace([np.nan, 0], [0, -1])
# 数据清理与转换(二) 去重复值
点击查看
"""数据清理与转换(二) 去重复值"""
import numpy as np
import pandas as pd
df1 = pd.DataFrame({'k1': ['a','a','b','c','c','c','a'], 'k2': [1, 1, 2, 3, 3, 4, 6]})
# print(df1)
# 1 duplicated()函数 [找出重复记录]
# df1.duplicated()
# 2.1 drop_duplicates()函数 [直接剔除对应的重复记录]
# df1.drop_duplicates()
# 2.2以列为单位比较是否存在重复记录[默认行为单位]
df1.drop_duplicates(['k1', 'k2'])
# 数据清理与转换(三) 索引重命名
点击查看
"""数据清理与转换(三) 索引重命名"""
import pandas as pd
# 1.df.rename(index={},columns={})方法
df1 = pd.DataFrame([[1111, 2222, 3333, 4444], [111, 222, 333, 444], [11, 22, 33, 44]])
# print(df1)
df1.rename(index={0:'row_1', 1:'row_2', 2:'row_3'}, columns={0:'col_1', 1:'col_2', 2:'col_3', 3:'col_4'})
# 数据清理与转换(四) 数据转换
点击查看
"""数据清理与转换(四) 数据转换"""
import pandas as pd
'''函数转换 map(Func)函数'''
# 1. 替换fillna replace(见前面)
# 2. map(Func)函数 [内部值进行函数转换。如统一字符的大小写等]
df1 = pd.DataFrame({"course":["Chinese", "math", "English", "physics" , "chemistry", "biologic"],
"score":[96, 94, 92, 62, 45, 60]})
# 2.1第一列转换为首字母大写
# df1['course'] = df1['course'].map(str.title) # upper
'''映射转换 map(Func)函数'''
# 1.根据字典的映射进行相应转换
course = {"Chinese":"语文", "math":"数学", "English":"英语", "physics":"物理", "chemistry":"化学", "biologic":"生物"}
df1['course'] = df1['course'].map(course)
df1
# 数据清理与转换(五) 数据离散化和装箱 指定划分边界
点击查看
"""数据清理与转换(五) 数据离散化和装箱"""
import pandas as pd
import numpy as np
"""
数值类型 1.连续值:一定区间可连续取值(比如天气的温度) 2.离散值:按一定顺序一一列举(比如'多云','晴天','雨天','阴天')
Categoricals: 1.是 pandas 的一种数据类型,是由固定的且有限数量的离散变量组成的 2.不能排序(sort_by): 顺序是创建时手工设定的,是静态的
"""
'''指定划分边界 cut()函数[实现数据装箱bin(连续->离散)。返回一个Categorical对象]'''
# arr = np.arange(0, 100, 7)
arr = np.random.randint(0, 100, 18) # 生成在半开半闭区间[low,high)上离散均匀分布的整数值
print(f"arr:{arr}")
bins = [0, 40, 80, 100]
cats = pd.cut(arr, bins)
# cats
print(f"编号:{cats.codes}") # 从0开始生成编号,不在范围内为-1
# 把array转换为DataFrame
df1 = pd.DataFrame( arr.reshape(3, 6) )
print(f"矩阵:\n{df1}")
df1[3] = pd.cut(df1[3], bins).values.codes
df1
# 数据清理与转换(五) 数据离散化和装箱 平均划分边界
点击查看
"""数据清理与转换(五) 数据离散化和装箱"""
import pandas as pd
import numpy as np
'''平均划分边界 cut()函数 可以通过数值平均等分(平均数)自动划分并装箱'''
arr = np.random.randint(0, 100, 18)
cats = pd.cut(arr, 4)
# print(f"装箱后矩阵:\n{cats.codes.reshape(3, 6)}")
df1 = pd.DataFrame( arr.reshape(3, 6) )
print(df1)
pd.DataFrame( cats.codes.reshape(3, 6) )
# cats
# 数据清理与转换(五) 数据离散化和装箱 分位划分边界
点击查看
"""数据清理与转换(五) 数据离散化和装箱"""
import pandas as pd
import numpy as np
'''分位划分边界 qcut(data,count) 使用中位数来划分数据并装箱'''
arr = np.random.randint(0, 100, 18)
cats = pd.qcut(arr, 4)
# print(f"装箱后矩阵:\n{cats.codes.reshape(3, 6)}")
df1 = pd.DataFrame( arr.reshape(3, 6) )
print(f"随机矩阵:{df1}")
print(f"cats:{cats}")
pd.DataFrame( cats.codes.reshape(3, 6) )
# 哑变量
点击查看
"""
哑变量(可以提高运算速度) 哑变量(dummy variable)是指用0或1表示某个类别是否出现
1. 有N种互斥属性时,哑变量需要引入N-1个变量,独热编码需要N个变量
2. get_dummies(drop_first=True)为真正哑变量,默认的drop_first=False为独热编码
"""
import pandas as pd
df1 = pd.DataFrame({"key":['a', 'b', 'a', 'c']})
# 独热编码
# pd.get_dummies(df1['key'])
# 哑变量
pd.get_dummies(df1['key'], drop_first=True)
# 连接哑变量
# 数据随机取样(排序)
点击查看
"""数据随机取样"""
import pandas as pd
import numpy as np
# 1.随机排序
df1 = pd.DataFrame({'k1': ['a','a','b','c','c','c'], 'k2': [1, 1, 2, 3, 3, 4]})
# sampler = np.random.permutation(6) # 生成随机序列
# df1.take(sampler) # 以随机序列为行索引,重新排序后输出
# 2.随机下采样 [随机排序后,取前n行]
sampler = np.random.permutation(len(df1))[:3] # simpler = array([x, x, x])
# 3.随机上采样 [样本较少时,扩大样本(),再取样]
## 生成12个元素在0 - 6范围内的数组(正态)
# sampler = np.random.randint(0, len(df1), size=2*len(df1))
df1.take(sampler)
# sampler
# 补充
点击查看
"""字符串操作"""
# 打印内置方法和属性
# dir(): 返回参数的属性、方法列表
# dir("")
# 编码解码
# "你好".encode()
b'\xe4\xbd\xa0\xe5\xa5\xbd'.decode('utf-8')
"""老师的代码"""
# 前缀使用
df=pd.DataFrame([[1,'a'],[2,'b'],[3,'c'],[1,'d'],[3,'e'],[2,'f']],columns=['lie1','lie2'])
print(df)
df1=pd.get_dummies(df['lie1'],prefix='lie1')
print(df1)
'''
一个对统计应用有用的秘诀是:结合get_dummies和cut之类的离散化函数
'''
#正态分布是个数值
data=np.random.rand(10)
print(data)
# [0.01472476 0.21786879 0.80685543 0.33888554 0.28585739 0.03260082
# 0.86698275 0.86326211 0.36818782 0.04061498]
#设置面元
bins=[0,0.2,0.4,0.6,0.8,1]
#面元划分
print(pd.cut(data,bins))
# [0.09044921 0.34034557 0.16417927 0.45625488 0.05030981 0.26397673
# 0.93966121 0.17444847 0.19196159 0.48356917]
# [(0.0, 0.2], (0.2, 0.4], (0.0, 0.2], (0.4, 0.6], (0.0, 0.2], (0.2, 0.4], (0.8, 1.0], (0.0, 0.2], (0.0, 0.2], (0.4, 0.6]]
# Categories (5, interval[float64]): [(0.0, 0.2] < (0.2, 0.4] < (0.4, 0.6] < (0.6, 0.8] < (0.8, 1.0]]
# (0.0, 0.2] (0.2, 0.4] (0.4, 0.6] (0.6, 0.8] (0.8, 1.0]
#哑变量
print(pd.get_dummies(pd.cut(data,bins)))
# Pandas聚合与分组
# 数据分组操作(1) (groupby函数 & series分组)
点击查看
"""数据分组操作(1) (groupby函数 & series分组)"""
import pandas as pd
import numpy as np
# 1.groupy()函数返回一个GroupBy对象,此对象没有做任何计算,只生成符合分组条件的中间数据,当执行apply方法时才进行真正的计算
df = pd.DataFrame({ 'k1':['a', 'a', 'b', 'b'], 'k2':['one', 'two', 'one', 'one'], 'v1':np.arange(4), 'v2':np.arange(6,10)})
'''单列分组'''
# grouped = df['v1'].groupby(df['k1'])
'''多列分组 (多层次索引的Series,可转化为DataFeame)'''
grouped = df['v1'].groupby([df['k1'], df['k2']])
# grouped # 显示GroupBy对象
print(df) # 打印df
# GroupBy对象在执行apply方法时,才会进行真正的计算和组合
## 如:在GroupBy对象上应用求平均的应用,并聚合输出一个新的Series
# grouped.mean()
pd.DataFrame(grouped.mean()) # 多层索引Series转化为DataFrame
# 数据分组操作(2) (DataFrme分组)
点击查看
"""数据分组操作(2) (DataFrme分组)"""
# np.array?? # help(np.array) # 查看方法详细信息
# DataFrame数据表对象,使用groupby()函数,指定分组的列,即可对数据表其它列进行应用和聚合
df = pd.DataFrame({'k1' : ['a', 'a', 'b', 'b'], 'k2' : ['one', 'two', 'one', 'one'],'v1' : np.arange(4), 'v2' : np.arange(6,10)})
print(df)
# 1. 单列分组
# 当被分组并应用汇聚的列,无法进行应用汇聚时,则直接丢弃(比如k2列为字符串,不能进行mean求平均值)
# df.groupby('k1').mean()
# 2.多列分组
# df.groupby(['k1', 'k2']).mean()
# 3.多列分组—去除分组索引
## 在多列分组的情况下,新生成的数据表会有多层次化索引,有的时候我们不需要这些索引,而是要将他们变成新的数据列
# df.groupby(['k1', 'k2'], as_index=False).mean()
# 4.自定义分组
# 如果我们不按照数据表中某列来分组,先自己定义分组的规则。这时,可以通过传入自定义列表传入groupby参数,按照列表数据规则进行分组
# df.groupby(['A', 'A', 'A', 'B']).mean()
# df.groupby(['1', '1', '2', '0']).mean()
# 5.多列分组—求和
# df.groupby(['1', '1', '2', '0']).sum()
# 6.多列分组—最大值
# df.groupby(['k1', 'k2']).max()
# 7.多列分组—中位数
# df.groupby(['k1', 'k2']).median()
df.groupby(['1', '1', '2', '1']).median()
# 数据分组操作(3) 分组指定应用聚合列
点击查看
"""数据分组操作(3) 分组指定应用聚合列"""
df = pd.DataFrame({'k1' : ['a', 'a', 'b', 'b'],'k2' : ['one', 'two', 'one', 'one'], 'v1' : np.arange(4),'v2' : np.arange(6,10)})
print(df)
# 1.指定单列 (运行没好使)
## 使用groupby()函数对DataFrame数据表进行分组时,可以指定方法应用和聚合的单列,并返回Series对象。series.groupby([“column_name”,”column_name”]).mean()
# df['v1'].groupby(['k1', 'k2']).mean()
# 1.2 指定单列—语法糖 (计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用)
## 什么是语法糖:https://www.jianshu.com/p/777b10385524
df.groupby(['k1', 'k2'])['v1'].mean()
# 2.指定多列 (运行没好使)
# df[['v1','v2']].groupby(['k1', 'k2']).mean()
# 2.1 指定多列—语法糖
df.groupby(['k1', 'k2'])['v1','v2'].mean()
# 数据分组操作(4) 分组的迭代操作
点击查看
"""数据分组操作(4) 分组的迭代操作"""
df = pd.DataFrame({ 'k1' : ['a', 'a', 'b', 'b'],'k2' : ['one', 'two', 'one', 'one'],'v1' : np.arange(4),'v2' : np.arange(6,10)})
# print(df)
# 对不同分组进行不同处理,对GroupBy对象进行迭代,在迭代中处理各个分组
# 1.输出分组
# for name, group in df.groupby('k1'):
# print("name:" + name)
# print(group)
# 2.
# for [k1, k2],group in df.groupby(['k1', 'k2']):
# print(f'({k1}, {k2}):\n{group}')
# 3.可以将分组数据变成数据表字典,dict(list(GroupByObj))
groupDict = dict(list(df.groupby('k1'))) # 先转列表再转字典
groupDict['a']
# 数据分组操作(5) 对行索引名进行分组
点击查看
"""数据分组操作(5) 对行索引名进行分组"""
df = pd.DataFrame({ 'k1':['a', 'a', 'b', 'b'], 'k2':['one', 'two', 'one', 'one'], 'v1':np.arange(4), 'v2':np.arange(6,10)},
index=['c1','cc2','cc3','c4'])
print(df)
# 1.行索引函数分组
df.groupby(len).mean()
# 2.行索引函数分组
df.index=['c1','cc2','cc3','c1'] # 重置索引
df.groupby(str).mean()
# df
# 数据分组操作(6) 聚合函数
点击查看
"""数据分组操作(6) 聚合函数"""
df = pd.DataFrame({'k1' : ['a', 'a', 'b', 'b'],'k2' : ['one', 'two', np.nan, 'one'], 'v1' : np.arange(4),'v2' : np.arange(6,10)})
print(df)
# 1.非空值计数
df.groupby('k1').count()
# 2. 分组乘积
# df.iloc[3, 2] = np.nan # 将3,2设为NaN
# df.groupby('k1').prod() # NaN不参与乘积
# 3.分组方差和标准差
# df.iloc[3, 2] = np.nan
# df.groupby('k1').var() # 方差
# df.groupby('k1').std() # 样本标准差 (numpy的是总体标准偏差???)
# 4.分位数
# df.iloc[3, 2] = np.nan
# df.groupby(['k1', 'k2']).quantile(0.75)
# 5.首尾值
# df.iloc[3, 2] = np.nan
# # df.groupby('k1').first()
# df.groupby('k1').last()
# 6.数据探索
## 在数据分析的数据探索阶段,需要对数据有个整体的感知,如果按上面步骤一个个看的话比较麻烦。Pandas提供describe()函数,可以生成常用方法结果
df.iloc[3, 2] = np.nan
df.groupby('k1').describe()
# 数据分组操作(7) 自定义聚合函数agg()
点击查看
"""数据分组操作(7) 自定义聚合函数agg()"""
df = pd.DataFrame({'k1' : ['a', 'a', 'b', 'b'],'k2' : ['one', 'two', np.nan, 'one'], 'v1' : np.arange(4),'v2' : np.arange(6,10)})
print(df)
def my_fun(data):
return data.max() + data.min()
df.iloc[3, 2] = np.nan
# 1.自定义函数
# df.groupby('k1').agg(my_fun)
# 2.自定义agg函数列表
# df.groupby('k1').agg(['mean', 'max', 'min', my_fun])
# 2.2 自定义agg函数列表 [指定应用结果的列名称(用元组)]
# df.groupby('k1').agg([('平均值', 'mean'), ('最大值', 'max'), ('最小值', 'min'), ("最大最小值之和", my_fun)])
# 2.3 自定义agg函数列表 [指定列名称(用元组) + 前缀add_prefix]
## 定义新数据表列名时,在同一行中命名会出现相同的情况,容易混淆
df.groupby('k1').agg( my_fun ).add_prefix('x_')
# 自定义聚合操作 分组转换与分组应用
点击查看
"""自定义聚合操作 分组转换与分组应用"""
df = pd.DataFrame({ 'k1' : ['a', 'a', 'b', 'b'],'k2' : ['one', 'two', np.nan, 'one'], 'v1' : np.arange(4),'v2' : np.arange(6,10)})
print(df)
# df.iloc[3,2] = np.nan
# 1.transform()函数 如果我们需要将统计结果参照原表的shape,直接广播到列中
# df.groupby('k1').transform(np.mean)
# df.groupby('k1').mean() # ?区别
# 2.GroupBy对象的transform()函数,与agg()一样可以传入自定义函数
def my_fun(data):
return data.max() + data.min()
# df.groupby(['k1', 'k2']).transform(my_fun) # ????????????????????不好使
df.groupby('k1')['v1', 'v2'].transform(my_fun)
# 3.agg和transform的区别
## agg()函数 必须是可以汇聚的值( aggregated value )
## transform()函数则可以传入普通的转换函数
# def divide(df,n=2):
# return df/n
# df.groupby('k1').agg(divide) # Exception: Must produce aggregated value
# df.groupby("k1")['v1','v2'].transform(divide)
# 通用的apply方法
点击查看
"""
通用的apply方法 可以是非汇聚函数
1. 通常,agg聚合生成的表shape小于原表,而apply和transform组合的shape可以等于原表
"""
'''
agg和transform的局限
agg()函数需要传入的方法可以返回汇聚的值( aggregated value ),transform()函数则可以是N:1的汇聚值,也可以是1对1的转换值。
如果是输入M到输出N的函数(M>N),agg和transform都无法使用!比如: 取分组的前N个值
'''
df = pd.DataFrame({ 'k1' : ['a', 'a', 'b', 'b'],'k2' : ['one', 'two', np.nan, 'one'], 'v1' : np.arange(4),'v2' : np.arange(6,10)})
def get_rows(df,n=2):
return df.iloc[:n,:]
# df.groupby('k1')['v1','v2'].agg(get_rows) # ValueError: Shape of passed values is (4, 2), indices imply (2, 2)
# df.groupby("k1")['v1','v2'].transform(get_rows) # IndexingError: ('Too many indexers', 'occurred at index v1')
# 1.取分组前N个值的方法
# df.groupby('k1')['v1','v2'].apply(get_rows,1)
# 2.也可以用apply()取TopN个值
def topn(df, n=3, column='sort_column'):
return df.sort_values(by=column,ascending=False)[:n]
df.groupby("k1")['v1','v2'].apply(topn,2,'v2')
# 透视表与交叉表 透视表(Pivot Table)
点击查看
""" 透视表与交叉表 透视表(Pivot Table)"""
import pandas as pd
'''
透视表(pivot table)是各种电子表格程序和其他数据分析软件中一种常见的数据汇总工具。它根据一个或多个键对数据进行聚合,并根据行和列上得分组建将数据分配到各个矩形区域中。
1. 在Python和pandas中,可以通过本章所介绍的groupby功能以及(能够利用层次化索引的)重塑运算制作透视表。
2. DataFrame有一个pivot_table方法,此外还有一个顶级的pandas.pivot_table函数。除了能为groupby提供便利之外,pivot_table还可以添加分项小计(也叫margins
'''
df = pd.DataFrame({ 'k1' : ['a', 'a', 'b', 'b'],'k2' : ['one', 'two', np.nan, 'one'], 'v1' : np.arange(4),'v2' : np.arange(6,10)})
# DataFrame.pivot_table(Index, Columns, aggFunc(默认为np.mean), fill_value)
# 1.如果只指定pivot_tabel()函数的index参数,不指定columns参数和fill_value参数,其结果和前面介绍的分组聚合结果一致。
# df.pivot_table(index='k1') # 相当于df.groupby('k1').mean()
# 2.指定输出的列
# df.pivot_table(['v1', 'v2'], index='k1') # 相当于df.groupby('k1')['v1', 'v2'].mean()
# 3.如果只指定pivot_tabel()函数的index参数,指定columns参数,就是将以列维度进行分组,其效果和指定两个分组行索引,再将返回的层次索引unstack() 结果一致
df.pivot_table(index='k1', columns='k2') # 相当于df.groupby(['k1', 'k2']).mean().unstack()
# 透视表与交叉表 交叉表(Cross Table)
点击查看
""" 透视表与交叉表 交叉表(Cross Table)"""
import pandas as pd
"""
1. 交叉表(cross table) 是矩阵格式的一种表格,显示变量的(多变量)频率分布。
2. 交叉表被广泛用于调查研究,商业智能,工程和科学研究。它们提供了两个变量之间的相互关系的基本画面,可以帮助他们发现它们之间的相互作用。
3. 卡尔·皮尔逊(Karl Pearson)首先在“关于应变的理论及其关联理论与正常相关性”中使用了交叉表。
4. 在pandas中,交叉表是一种特殊的透视表。
"""
# pd.crosstab(index, columns, margins[边际求和开关])
df = pd.DataFrame({ 'k1' : ['a', 'a', 'b', 'b'],'k2' : ['one', 'two', np.nan, 'one'], 'v1' : np.arange(4),'v2' : np.arange(6,10)})
def get_rows(df,n=2):
return df.iloc[:n,:]
df.iloc[3,2] = np.nan
# pd.crosstab(df['k1'],df['k2'])
pd.crosstab(df['k1'],df['k2'],margins=True)
# Seaborn(Pandas)可视化
折线图
点击查看
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.DataFrame(np.random.randn(10,3), columns = ['A','B','C'], index = np.arange(0,100,10))
df.plot()
plt.show()
# df
条形图
点击查看
fig, axes = plt.subplots(1,2)
data = pd.Series(np.random.rand(7),index = list('abcdefg'))
#kind选择图表类型 'bar' 垂直条形图
data.plot(kind = 'bar', ax = axes[0], color = 'b', alpha = 0.7)
# 'barh' 水平条形图
data.plot(kind = 'barh', ax = axes[1], color = 'b', alpha = 0.7)
plt.show()
直方图
点击查看
import sklearn.datasets as skds
"""直方图"""
# iris = skds.load_iris()
# df_iris = pd.DataFrame(iris.data,columns=iris.feature_names)
# df_iris.hist('sepal length (cm)')
# plt.show()
iris = skds.load_iris()
df_iris = pd.DataFrame(iris.data,columns=iris.feature_names)
df_iris.hist()
plt.show()
## --------------------------------------------
fig, axes = plt.subplots(1,2)
data = pd.Series(np.random.randn(100))
data.hist(ax = axes[0], bins = 50) #直方图
data.plot(kind = 'kde', ax = axes[1]) #密度图
plt.show()
散点图
点击查看
iris = skds.load_iris()
df_iris = pd.DataFrame(iris.data,columns=iris.feature_names)
df_iris.plot(kind='scatter',x="sepal length (cm)", y="sepal width (cm)")
plt.show()
Matplotlib无疑是高度可定制的,但快速实施出吸引人的细节就变得有些复杂。Seaborn作为一个带着定制主题和高级界面控制的Matplotlib扩展包,能让绘图变得更轻松
示例
点击查看
"""Seaborn可视化方法 (单变量分布)"""
import seaborn as sns
"""最快速查看单变量分布无疑是使用distplot()函数。默认情况下,这将绘制一个直方图,并拟合出核密度估计(KDE)"""
x = np.random.normal(size=100)
sns.distplot(x)
plt.show()
# ---------------------------------
"""Seaborn可视化方法 (直方图)"""
"""
直方图通过在数据的范围内切成数据片段,然后绘制每个数据片段中的观察次数,来表示整体数据的分布。
我们删除密度曲线并添加了地毯图,每个观察点绘制一个小的垂直刻度
"""
x = np.random.normal(size=100)
sns.distplot(x, kde=False, rug=True)
plt.show()
## ---------------------------------
"""Seaborn可视化方法 (核密度估计)"""
"""Seaborn的displot()函数,通过设置参数,可以实现只显示核密度估计和地毯图"""
x = np.random.normal(size=100)
sns.distplot(x, hist=False, rug=True)
plt.show()
## ---------------------------------
"""Seaborn可视化方法 (散点双变量分布)"""
# 随机生成两列,其均值为[0,1],协方差矩阵为[(1, 0.5), (0.5, 1)]的数组
mean, cov = [0, 1], [(1, 0.5), (0.5, 1)]
data = np.random.multivariate_normal(mean, cov, 200)
df = pd.DataFrame(data, columns=["x", "y"])
sns.jointplot(x="x", y="y", data=df)
plt.show()
## ---------------------------------
"""Seaborn可视化方法 (成对关系图)"""
"""
要在数据集中绘制多个成对双变量分布,可以使用pairplot()函数。这将创建一个轴的矩阵,并显示DataFrame中每对列的关系。
默认情况下,它也绘制每个变量在对角轴上的单变量。
"""
import sklearn.datasets as skds
iris = skds.load_iris()
df_iris = pd.DataFrame(iris.data,columns=iris.feature_names)
sns.pairplot(df_iris)
plt.show()
## ---------------------------------
"""Seaborn可视化方法 (线性回归线一)"""
"""Seaborn的lmplot(data,x,y)函数,将data数据表中x列和y列数据,生成散点图,并绘制线性回归线。本示例使用tips数据集。"""
# tips = sns.load_dataset("tips")
tips = pd.read_csv('./data/tips.csv')
sns.lmplot(data=tips, x="total_bill", y="tip")
plt.show()
## ---------------------------------
"""Seaborn可视化方法 (线性回归线二)"""
"""Seaborn的jointplot()函数绘制双变量分布时,也可以绘制回归线。设置kind参数为“reg”。本示例使用tips数据集。效果如下"""
# tips = sns.load_dataset("tips")
tips = pd.read_csv('./data/tips.csv')
sns.jointplot(x="total_bill", y="tip", data=tips, kind="reg")
plt.show()
# tips
## ---------------------------------
"""生成数据"""
import csv
import random
import datetime
filepath ='data/data.csv'
with open(filepath, 'w', encoding='utf-8') as fp:
#创建csv文件写入对象
wr = csv.writer(fp)
#写入表头
wr. writerow(['日期','销量'])
#生成模拟数据
startDate = datetime. date(2020, 1, 1)
#生成365个模拟数据,可以根据需要进行调整
for i in range (365):
#生成一个模拟数据,写入csv文件
amount = 300 + i*5 + random.randrange (100)
wr.writerow([str(startDate), amount] )
#下一天
startDate = startDate + datetime.timedelta (days=1)
"OK"
## ---------------------------------
"""生成模拟数据"""
import numpy as np
import pandas as pd
# 用含日期时间索引与标签的 NumPy 数组生成 DataFrame
dates = pd.DataFrame(pd.date_range("20200101", periods=365), columns=['日期'])
data = pd.DataFrame(np.random.randint(300, 600, dates.shape[0]), columns=['销量'])
df = dates.join(data)
filepath = 'data\data0.csv'
df.to_csv(filepath, # sys.stdout, # 输出到控制台
na_rep='non', # 存储空值
index=False, # 不存储索引(index)
header=True, # 存储列名
)
## ---------------------------------
import pandas as pd
import matplotlib.pyplot as plt
# 读取数据,丢弃缺失值
df = pd.read_csv('data\\data0.csv', encoding='utf-8')
df = df.dropna()
# print(df['日期'])
# 设置字体
plt.rcParams['font.sans-serif']=['LiSu']
plt.rcParams['axes.unicode_minus'] = False
#生成营业额折线图
plt.figure()
df.plot(x='日期')
# plt.savefig('data\\test\\first.jpg')
#按月统计,生成柱状图
plt.figure()
df1 = df[:]
# map()会根据提供的函数对指定序列做映射。第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表
# lambda简化了函数定义的书写形式。使代码更为简洁,但是使用函数的定义方式更为直观,易理解。
# def fun(x):
# return x[:x.rindex('-')]
df1['month'] = df1['日期'].map(lambda x:x[:x.rindex('-')]) # lambda x:x[:x.rindex('-')]
df1 = df1.groupby(by='month', as_index=False).sum()
df1.plot(x='month', kind='bar')
# plt.savefig('data\\test\\second.jpg')
# 查找涨幅最大的月份,写入文件
plt.figure()
df2 = df1.drop('month', axis=1).diff()
# DataFrame.nlargest(self, n, columns, keep='first') 返回按列降序排列的前n行。以降序返回column中具有最大值的前n行。未指定的列也将返回,但不用于排序。
# 此方法等效于 ,但性能更高。df.sort_values(columns, ascending=False).head(n)
m = df2['销量'].nlargest(1).keys()[0]
print(f"销量最高月份{df1.loc[m, 'month']}")
with open('data\\test\\maxMonth.txt', 'w') as fp:
fp.write(df1.loc[m, 'month'])
# 按季度统计,生成饼状图
plt.figure()
one=df1[:3]['销量'].sum()
two=df1[3:6]['销量'].sum()
three=df1[6:9]['销量'].sum()
four=df1[9:12]['销量'].sum()
plt.pie([one, two, three, four], labels=['第一季度', '第二季度', '第三季度', '第四季度'])
# plt.savefig('data\\test\\third.jpg')
plt.show()
# matplotlib可视化
# 条形图
# 条形图
点击查看
"""第一次作业 条形图"""
import pymysql
import matplotlib.pyplot as plt
# from matplotlib import font_manager
##获取一个数据库连接,注意如果是UTF-8类型的,需要制定数据库
db=pymysql.connect(host="127.0.0.1",user='root',passwd="123456789",port=3306,db="demo",charset='utf8')
cursor=db.cursor()#获取一个游标
sql="select city,need from citys"
cursor.execute(sql)
result=cursor.fetchall() #result为元组
cursor.close() #关闭游标
db.close() #关闭数据库
#将元组数据存进列表中
city=[]
need=[]
for x in result:
city.append(x[0])
need.append(x[1])
# 一种设置字体的方式
# my_font = font_manager.FontProperties(fname="D:\software\python\Anaconda3\Library\MyFonts\GeiTangBuDaoDan.ttf")
# 设置字体
plt.rcParams['font.sans-serif']=['LiSu']
plt.rcParams['axes.unicode_minus'] = False
# 设置图形大小
plt.figure(figsize=(12, 5), dpi=120)
# 设置刻度字体大小
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
#直方图
plt.bar(range(len(need)), need, color='r', tick_label=city)
plt.xlabel("城市名", fontsize=20)
plt.ylabel("数量", fontsize=20)
plt.title("城市职位需求图", fontsize=20)
for x,y in enumerate(need):
plt.text(x-0.4, y+0.4, '%s' % y)
plt.show()
# 条形图 bar()
点击查看
"""条形图 bar()"""
import pandas as pd
import matplotlib.pyplot as plt
# 示例
# plt.bar(np.arange(2,5),np.arange(1,4),
# label="zt example")
# plt.bar([1,2,3],[2,4,1],label="tz example", color='g')
# plt.xlabel("this is x")
# plt.ylabel("this is y")
# plt.title("this is bar")
# plt.legend()
# plt.show()
"""展示2017票房数据"""
# 设置字体
plt.rcParams['font.sans-serif'] = ['LiSu']
plt.rcParams['axes.unicode_minus'] = False
# 1.设置图片大小
# 实例化figure并传递参数 dpi为每英寸像素点数
fig = plt.figure(figsize=(8, 4), dpi=200)
movie_name = ["战狼2","速度与激情8","功夫瑜伽","西游伏妖篇","变形金刚5:最后的骑士","摔跤吧!爸爸","加勒比海盗5:死无对证","金刚:骷髅岛","极限特工:终极回归","生化危机6:终章","乘风破浪","神偷奶爸3","智取威虎山","大闹天竺","金刚狼3:殊死一战","蜘蛛侠:英雄归来","悟空传","银河护卫队2","情圣","新木乃伊",]
box_office = [56.01,26.94,17.53,16.49,15.45,12.96,11.8,11.61,11.28,11.12,10.49,10.3,8.75,7.55,7.32,6.99,6.88,6.86,6.58,6.23]
df = pd.DataFrame( {"电影名":movie_name, "票房(单位:亿)":box_office} )
# df
x = range(df.shape[0]) # x轴的列表
y = box_office
# bar()绘制条形图,只能接受可迭代的数字对象
plt.bar(x, y,
width = 0.4, # 默认0.8
color = 'orange',
tick_label = y,
label = '电影', # 为设置图例作准备
alpha = 0.9
)
# 通过设置xticks使数字与字符串对应
plt.xticks(x, df.iloc[:, 0], rotation=90)
# 设置描述信息
plt.title("2017年电影票房展示")
plt.xlabel(df.columns[0])
plt.ylabel(df.columns[1])
# 显示图例
plt.legend()
plt.show()
# 水平条形图 barh()
点击查看
"""水平条形图 barh()"""
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
"""展示2017票房数据"""
movie_name = ["战狼2","速度与激情8","功夫瑜伽","西游伏妖篇","变形金刚5:最后的骑士","摔跤吧!爸爸","加勒比海盗5:死无对证","金刚:骷髅岛","极限特工:终极回归","生化危机6:终章","乘风破浪","神偷奶爸3","智取威虎山","大闹天竺","金刚狼3:殊死一战","蜘蛛侠:英雄归来","悟空传","银河护卫队2","情圣","新木乃伊",]
box_office = [56.01,26.94,17.53,16.49,15.45,12.96,11.8,11.61,11.28,11.12,10.49,10.3,8.75,7.55,7.32,6.99,6.88,6.86,6.58,6.23]
df = pd.DataFrame( {"电影名":movie_name, "票房(单位:亿)":box_office} )
# df
# 设置字体
plt.rcParams['font.sans-serif'] = ['LiSu']
plt.rcParams['axes.unicode_minus'] = False
# 1.设置图片大小
# 实例化figure并传递参数 dpi为每英寸像素点数
fig, ax = plt.subplots(figsize=(20, 16), dpi=80)
x = np.arange(df.shape[0]) # x轴的列表
y = box_office
# bar()绘制条形图,只能接受可迭代的数字对象
plt.barh(x, y,
height = 0.4,
color = 'orange',
label = '电影', # 为设置图例作准备
alpha = 0.9,
align='center'
)
# plt.yticks(y, movie_name) # , rotation=90
ax.set_yticks(x)
ax.set_yticklabels(df.iloc[:, 0], minor=False, fontsize=16)
ax.invert_yaxis() # 标签读取自上而下labels read top-to-bottom
# 设置描述信息
ax.set_title("2017年电影票房展示", fontsize=20)
ax.set_xlabel(df.columns[1], fontsize=20)
ax.set_ylabel(df.columns[0], fontsize=20)
# 显示图例
ax.legend()
plt.show()
# 子图
点击查看
"""子图"""
import pandas as pd
import matplotlib.pyplot as plt
##获取一个数据库连接,注意如果是UTF-8类型的,需要制定数据库
db=pymysql.connect(host="127.0.0.1",user='root',passwd="123456789",port=3306,db="demo",charset='utf8')
cursor=db.cursor()#获取一个游标
sql="select city,need from citys"
cursor.execute(sql)
result=cursor.fetchall() #result为元组
col_result = cursor.description # 获取查询结果的字段描述
cursor.close() #关闭游标
db.close() #关闭数据库
# 设置字体
plt.rcParams['font.sans-serif']=['LiSu']
plt.rcParams['axes.unicode_minus'] = False
# 设置图形大小
plt.figure(figsize=(20, 10), dpi=120)
fig, axes = plt.subplots(1, 2)
# 用数据库查询到的数据创建DataFrame
# print(col_result)
df = pd.DataFrame(result, columns=[col_result[0][0], col_result[1][0]])
# 饼图
slices = df.iloc[:, 1]
activities = df.iloc[:, 0]
axes[0].pie(slices,labels=activities,
startangle=90, # 初始角度
shadow= True, # 阴影
textprops={'size': 'small'},
# colors=[], # 设置颜色
# radius=1.6, # 半径
explode=(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.05, 0), # 突出
autopct='%1.2f%%') #
# 条形图
axes[1].bar(df.iloc[:, 0], df.iloc[:, 1], color='pink')
# axes[1].xt
plt.title('城市职位需求图')
plt.show()
# 饼图
点击查看
"""第二次作业 饼图"""
import pandas as pd
import matplotlib.pyplot as plt
##获取一个数据库连接,注意如果是UTF-8类型的,需要制定数据库
db=pymysql.connect(host="127.0.0.1",user='root',passwd="123456789",port=3306,db="demo",charset='utf8')
cursor=db.cursor()#获取一个游标
sql="select city,need from citys"
cursor.execute(sql)
result=cursor.fetchall() #result为元组
col_result = cursor.description # 获取查询结果的字段描述
cursor.close() #关闭游标
db.close() #关闭数据库
# 设置字体
plt.rcParams['font.sans-serif']=['LiSu']
plt.rcParams['axes.unicode_minus'] = False
# 设置图形大小
plt.figure(figsize=(6, 4), dpi=120)
# 用数据库查询到的数据创建DataFrame
# print(col_result)
df = pd.DataFrame(result, columns=[col_result[0][0], col_result[1][0]])
# 饼图
slices = df.iloc[:, 1]
activities = df.iloc[:, 0]
plt.pie(slices,labels=activities,
startangle=90, # 初始角度
shadow= True, # 阴影
textprops={'size': 'small'},
# colors=[], # 设置颜色
# radius=1.6, # 半径
explode=(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.05, 0), # 突出
autopct='%1.2f%%') #
plt.title('城市职位需求图')
plt.show()
# 折线图(完整)
点击查看
"""折线图 (画出你和同桌在11-25岁谈过的女友数) """
import matplotlib.pyplot as plt
import numpy as np
# 设置字体
plt.rcParams['font.sans-serif'] = ['LiSu']
plt.rcParams['axes.unicode_minus'] = False
# 1.设置图片大小
# 实例化figure并传递参数 dpi为每英寸像素点数
fig = plt.figure('Figure Object 1', # 图形对象名称 窗口左上角显示
figsize=(8, 4), # 窗口大小
dpi=80, # 分辨率
facecolor = 'white', # 背景色
)
# x轴和y轴
x = range(11, 31)
y_1 = [1, 0, 1, 1, 2, 4, 3, 2, 3, 4, 4, 5, 6, 5, 4, 3, 3, 1, 1, 1]
y_2 = [1, 0, 3, 1, 2, 2, 3, 3, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1]
plt.plot(
x,
y_1,
# 折线样式
color='r', # 设置线条颜色
linestyle='--', # 线条风格
linewidth=1, # 线条粗细
alpha=0.5, # 透明度
label='自己',
# 6.折点样式设置
marker='o', # 折点形状
markersize='3', # 或 ms --折点大小
markerfacecolor='black', # 或 mfc --折点实心颜色
)
plt.plot(
x,
y_2,
color='b', # 设置线条颜色
linestyle=':', # 线条风格
linewidth=1, # 线条粗细
alpha=0.5, # 透明度
label='同桌',
# 折点样式设置
marker='*', # 折点形状
markersize='6', # 或 ms --折点大小
markerfacecolor='pink', # 或 mfc --折点实心颜色
)
# 8.标出最高点 (因为横纵坐标没有必然联系所以比较难整)
zip1 = dict( zip(x, y_1) ) # 把横纵坐标合为一个字典
# 找出最大值和下标
for key,value in zip1.items():
if(value == max(zip1.values())):
max_index1 = key
max_value1 = value
del zip1
plt.plot(max_index1,max_value1,'ks')
s = f"({max_index1},{max_value1})"
# plt.annotate()函数用于标注文字
plt.annotate(s, xytext=(max_index1,max_value1), xy=(max_index1,max_value1)) # 注释内容 注释文本的坐标点 被注释的坐标点,二维元组形如(x,y)
####
zip2 = dict( zip(x, y_2) ) # 把横纵坐标合为一个字典
# 找出最大值和下标
for key,value in zip2.items():
if(value == max(zip2.values())):
max_index2 = key
max_value2 = value
del zip2
plt.plot(max_index2,max_value2,'ks')
s = f"({max_index2},{max_value2})"
# plt.annotate()函数用于标注文字
plt.annotate(s, xytext=(max_index2,max_value2), xy=(max_index2,max_value2))
# 4.调整x和y轴刻度间距
_xtick_labels = ["{}岁".format(i) for i in x]
plt.xticks(x, _xtick_labels, rotation=45, fontsize=9)
plt.yticks(range(0, 9))
# 5.线条样式 颜色 透明度
# 加网格 (透明度)
plt.grid(alpha=0.5, linestyle='--', linewidth=1)
# 3.描述信息(x轴[y轴.标题]代表什么)
plt.xlabel('年龄')
plt.ylabel('人数')
plt.title("回忆青葱岁月", fontsize=16)
plt.legend(loc='best')
# 2.保存到本地 (可设置格式(svg矢量图))
# plt.savefig("data/xxx.svg")
# 7.图片加水印
def add_watermark(x, y):
fig.text(x, y, '寒川环宇', # text的位置,内容
fontsize=16,
color='gray',
ha='left',
va='top',
rotation=-45, #旋转角度
alpha=0.3,
bbox = dict(facecolor = "#B0C4DE", alpha = 0.05)) # 加框(框体颜色,透明度)
add_watermark(0.5, 0.6)
add_watermark(0.5, 0.8)
add_watermark(0.2, 0.6)
add_watermark(0.2, 0.8)
plt.show()
编辑 (opens new window)
上次更新: 2022/05/03, 23:36:40