使用 Pandas 和 NumPy 高效处理数据

安装pandas和numpy

      pip install pandas
pip install numpy
pip uninstall numpy
pip install numpy==2.0.2

    

一般情况下numpy和pandas都按照的有,如果没有安装就使用上面的命令安装。还可以安装指定版本的numpy。

pandas和numpy的使用场景

下面的示例都是尽量介绍通用的函数,新的函数可能旧版本的不支持。

0.数据读取与导出

导入pandas和numpy这2个包

      import pandas as pd
import numpy as np

    

cd /mnt/e/MearchineLearning/传统机器学习/data/titanic/

读取文件

此处使用的是泰坦尼克号的数据集,可以关注公众号“小猫学生信”,发送“泰坦尼克”或“titanic”获取数据集。

读取时缺失值的处理

输出文件

      df.to_csv('train.txt',sep='\t',index=False)
df.to_csv('output.csv', sep='|', header=True, index=False, encoding='utf-8')

    

输出时

1.数据结构和基本操作

查看数据

查看前n行
查看后n行
查看数据框每列的数量

df.count()

      PassengerId    891
Survived       891
Pclass         891
Sex            891
Age            714
SibSp          891
Parch          891
Fare           891
Cabin          204
Embarked       889
dtype: int64

    
查看数据框的结构

df.info() 会输出数据框的结构,

      <class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 10 columns):
 #   Column       Non-Null Count  Dtype
---  ------       --------------  -----
 0   PassengerId  891 non-null    int64
 1   Survived     891 non-null    int64
 2   Pclass       891 non-null    int64
 3   Sex          891 non-null    object
 4   Age          714 non-null    float64
 5   SibSp        891 non-null    int64
 6   Parch        891 non-null    int64
 7   Fare         891 non-null    float64
 8   Cabin        204 non-null    object
 9   Embarked     889 non-null    object
dtypes: float64(2), int64(5), object(3)
memory usage: 69.7+ KB

    

#####查看数据框的数据均值和极值

          PassengerId    Survived      Pclass         Age       SibSp       Parch        Fare
count   891.000000  891.000000  891.000000  714.000000  891.000000  891.000000  891.000000
mean    446.000000    0.383838    2.308642   29.699118    0.523008    0.381594   32.204208
std     257.353842    0.486592    0.836071   14.526497    1.102743    0.806057   49.693429
min       1.000000    0.000000    1.000000    0.420000    0.000000    0.000000    0.000000
25%     223.500000    0.000000    2.000000   20.125000    0.000000    0.000000    7.910400
50%     446.000000    0.000000    3.000000   28.000000    0.000000    0.000000   14.454200
75%     668.500000    1.000000    3.000000   38.000000    1.000000    0.000000   31.000000
max     891.000000    1.000000    3.000000   80.000000    8.000000    6.000000  512.329200

    

包含每列的非空值的数量,均值,标准差,最小值和最大值。

从字典、列表、numpy数组创建DataFrame

      #创建1个字典
customer={
    'name': ['Alice', 'BobLi', 'Charlie'],
    'age': [25, 30, 35],
    'salary': [50000, 40000, 70000]
}

df=pd.DataFrame(customer) #把字典转为数据框
location=['Hongkong','Peking','Xi\'an'] #创建一个列表
df['location']=location #新增一列


    

索引和列的选择(切片) 难点和重点

#####添加、删除列

2.iloc和loc的使用

两者的区别:

df.loc[行名,列名]

筛选满足条件的所有列

df.loc[df['age']>25]

筛选满足条件的指定列

df.loc[df['age']>25,['salary','name']]

筛选多个条件,每个条件内部使用小括号包裹住。

df.loc[(df['age']>25) & (df['salary']>50000)]

设置行名(索引)

      df['new_index']=['first','second','third']
df.set_index('new_index')

    
      df2=df.set_index('new_index')
df2.reset_index() #把原来的索引列转变为1列正常的列,索引恢复为默认数字
df2.reset_index(drop=True) #不保留原来的索引列,索引恢复为默认数字

    

选择行

新增一列 df['gender']=['man','woman','man']

      df['new_index']=['first','second','third']
df.set_index('new_index',inplace=True) #原地修改,增加行名
df.loc['first'] #筛选行名是first的行
df.loc['first':'third'] #筛选first行到third行
df.loc[['first','third']] #筛选first和third行

    

选择列

      un_use_col=['location','age']
df2=df.drop(columns=un_use_col) #这里是删除了不用的列赋值给新的变量
df3=df[df.columns.difference(un_use_col)] #这里是排除了不用的列赋值给新的变量

    

df2和df3的内容是相同的。

iloc进行筛选

iloc筛选是基于数字位置索引,所以区间是左闭右开。不包含右边区间的值。注意区间的格式是整数:整数df.iloc[x轴,y轴]

3.使用numpy对数组进行操作

注意:数组的维度最小是1,要和数组的索引是从0开始区分开。

numpy创建数组

      list1=[1,3,5,7,8,'test','True',100]
new_arr=np.array(list1) #把列表转为1维数组
new_arr2=new_arr.reshape(2,4) #把1维度数组转为2维度,此处是2行4列
new_arr2.reshape(8)  #把2维度数组转回1维
new_arr3=new_arr2.reshape(1,4,2) #把2维度数组转为3个维度

    

获取数组的信息

new_arr3.ndim 返回3

array索引和切片

      arr=np.arange(1,16).reshape(3,5) #创建3行5列数组

arr[-1,-1] #15 获取最后一行最后一列的那个元素
arr[:,4] #获取第4列的值,
arr[arr>3] #获取数组中所有大于3的元素,返回是1维的数组

    

广播机制(Broadcasting) 这是numpy的核心优势,相比于传统循环加速最明显 难点和重点

主要是深度学习需要用到矩阵和数组的运算

Broadcasting的作用是在执行算数运算时,自动将性状较小的数组扩展以匹配较大数组的形状,从而完成逐个元素运算。

标量和数组的运算

      arr=np.array([1,3,5])
scale=10
result=arr*scale
print(result)

    

标量可以和任意数组运算

向量和矩阵的运算

      A = np.array([[1,3,5],[2,4,8]])
B = np.array([-1,25,10])
result2 = A + B
print(result2)

    

列向量和行向量

      row=np.array([1,2,3])
col=np.array([[25],[22]]) 
row + col 

    

常用的numpy内置函数

numpy的数学函数

数组和list, DataFrame互相转换

      df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6],
    'C': [7, 8, 9]
})
arr=df.to_numpy() #转为数组
arr2=df.values    #转为数组  

    

注意:数据框转为数组后会丢失列名。

      df2=pd.DataFrame(arr,columns=['A','B','C'])

    

此处转为数据框需要提供列名,df2和df的内容一样。但是有的时候数据类型会改变。

使用df.dtypesdf2.dtypes查看每列的数据类型。

创建随机数组

np.random.seed(101) #设置随机数的种子 设置随机数的种子对于科学研究非常重要,可以保证结果可以复现

      import numpy as np
np.random.seed(9527)
a=np.random.randint(0,100,10)
b=np.random.randint(0,100,10)
print(a,b)

    

上面的输出结果是:(即使你使用的是不同版本的numpy,也应该输出下面的结果)

      [97  8 16 48 76  8 92 48  1 87] [59 84 75 41 34 53 16 24 95 24]

    

从指定数组随机抽样

      str_num = [2,1,'a','f','l','3','o','!','A','B','@']
np.random.choice(str_num,size=8,replace=True)  #有放回的随机抽取8个值,所以可能会有重复的字符串
np.random.choice(str_num,size=8,replace=False)  #随机抽取8个值,每个值只能被抽到1次

    
      num_arr=np.arange(0,10)  #生成0-9这10个整数
np.random.choice(num_arr,size=6) #这就生成了6位随机数

    
      import numpy as np
def get_strong_password(seed,pass_length=8):
	np.random.seed(seed)
	if pass_length < 8:
		raise ValueError("密码的程度至少为8")
	#定义4种不同类型的数组
	digits = np.array(list('0123456789'))
	uppercase = np.array(list('ABCDEFGHIJKLMNOPQRSTUVWXYZ'))
	lowercase = np.array(list('abcdefghijklmnopqrstuvwxyz'))
	symbols = np.array(list('+-/!@#$%^&*?[]{}'))

	#每种类型的数组随机抽取1个,即每个类型的最少出现1次
	part1=np.concatenate([
		np.random.choice(digits,size=1,replace=True),
		np.random.choice(uppercase,size=1,replace=True),
		np.random.choice(lowercase,size=1,replace=True),
		np.random.choice(symbols,size=1,replace=True)
	])
	#计算数组的长度
	part1_len=part1.size #获取一维数组的长度
	part2_len=pass_length - part1_len #获取还需要生成多少位字符
	#合并所有的类型到一个一维数组
	total_str = np.concatenate([digits,uppercase,lowercase,symbols])
	#抽取剩余的位数的字符串
	part2=np.random.choice(total_str,size=part2_len)

	#合并part1和part2
	password=np.concatenate([part1,part2])
	#打乱数组元素的顺序
	np.random.shuffle(password)
	#转为字符串
	return ''.join(password)

mima=get_strong_password(seed=101,pass_length=12)
print(mima)

    

上面就是一个完整的生成强密码的随机数程序,每次用户只要使用相同的seed和pass_length位数,就能获得同一个密码。

      weights = [0.99,0.009,0.0009,0.0001]
arr=['三等奖','二等奖','一等奖','特等奖']
score=np.random.choice(arr,size=10,p=weights)

    

这样一个抽奖系统的底层逻辑就写好了,权重数组weights的总和必须等于1.此处你抽到特等奖的概率就是万里挑一。 你还怕有人抽到特等奖,那就直接给它的权重设置为0.