Pandas(一)—— Pandas基础

Pandas(一)—— Pandas基础

大家可以关注知乎或微信公众号的share16,我们也会同步更新此文章。

一、预备知识

   我们之前学到的一些知识,在pandas中也会应用到,我们在此总结一下:

1.1 Python基础

  • 各种推导式,如列表/元组推导式等,我们在以前的文章中可以了解到,如:‘ Python基础(三/四)—— XXX的创建 ’版块中可以查询到;
  • 函数,如def、lambda、map等,我们可以在‘ Python基础(五)’这篇文章中查询到;
  • zip对象与enumerate方法:zip函数能够把多个可迭代对象打包成一个元组构成的可迭代对象,它返回了一个zip对象,通过tuple、list可以得到相应的打包结果;enumerate是一种特殊的打包,它可以在迭代时绑定迭代元素的遍历序号;
# zip函数 
l1 = 'abc';l2 = 'def';l3 = 'ghi';
print(zip(l1,l2,l3), list(zip(l1,l2,l3)), tuple(zip(l1,l2,l3)), sep='\n\n')
for x,y,z in zip(l1,l2,l3):
    print(x,y,z)

# enumerate函数
for i in enumerate(l1):
    print(i)    
for m,n in enumerate(l1):
    print(m,n)

# 当需要对两个列表建立字典映射时,可以利用zip对象
dict(zip(l1,l2))

1.2 NumPy基础

  • 创建数组、数组的变形和合并;补充:对于二维数组而言,r_和c_分别表示上下合并和左右合并,如:np.r_[a,b]和np.c_[a,b];
  • 常用函数,如:where、nonzero/argmax/argmin、any/all、mean/std/var/cov/corrcoef等;向量与矩阵的计算;
  • 以上,我们可以在‘ NumPy ’文章中查询到;

1.3 练习

1.3.1 利用列表推导式写矩阵乘法
import numpy as np
a = np.random.randint(5, 15, (2,3))
b = np.random.randint(6, 18, (3,4))

# 创建一个m行n列的数组
res = np.empty((a.shape[0], b.shape[1])) 

for i in range(a.shape[0]):
    for j in range(b.shape[1]):
        res[i][j] = sum(a[i,:]*b[:,j]) # a的第i行 乘以 b的第j列
print('a是:\n{}\n\nb是:\n{}\n\n矩阵乘法是:\n{}\n'.format(a,b,res))

if np.allclose(np.dot(a,b),res ):
    print('结果没有问题。')
else:
    print('结果有问题,请再检查一下。')
1.3.2 更新矩阵

在这里插入图片描述

import numpy as np
a = np.arange(1,16).reshape(3,-1)
b = np.empty(a.shape)

for i in range(len(a)):
    for j in range(len(a[i])):
        b[i][j] = a[i][j] * sum(np.reciprocal(a[i], dtype=float)) 
        #注:此处要定义dtype
        # 等价于 b[i][j] = a[i][j] * sum(1/a[i])

print(a, b, sep='\n\n')
1.3.3 连续整数的最大长度

在这里插入图片描述

import numpy as np
a = np.array(eval(input('请输入正整数,用英文逗号分隔:')))

while a.dtype != int:
    print('输入的数据不是正整数,请重新输入!')
    a = np.array(eval(input('请输入正整数,用英文逗号分隔:'))) 

b = np.nonzero( np.diff(a) != 1)[0] #返回非零元素的索引
c = np.split(a,b+1)  # 分隔数组
lst = [len(i) for i in c] # 列表推导式
for m,n in enumerate(lst):
    if n == max(lst):
        print(c[m], len(c[m]))

二、Pandas基础

2.1 文件的读取和写入

   读取:read_csv、read_excel、read_table等;
   写入:to_csv、to_excel等;
在这里插入图片描述

2.2 基本数据结构

2.2.1 Series

   Pandas Series 类似表格中的一个列,类似于一维数组,可以保存任何数据类型。

Series 函数如下:pd.Series(data,index,dtype,name,copy)

  • index:数据索引标签,如果不指定,默认从 0 开始;
  • dtype:数据类型,默认会自己判断;
  • name:赋予Series 名称;
  • copy: 拷贝数据,默认为 False;

dir(pd.Series):查看Series的相关属性/函数

import numpy as np
import pandas as pd 

x = [[1,2,3],[4,5,6]]

'''  data:是列表 '''
a = pd.Series(x, index=['a','b'], name='matrix', copy=False)
print(a, end='\n\n')

''' data:是数组,数组必须是一维的 '''
b = pd.Series(np.array(x)[0])
print(b, end='\n\n')

''' data:是字典 '''
print(pd.Series(dict(zip(x[0], x[1]))), pd.Series(dict(enumerate(x))), sep='\n\n')

# 运行结果
# a    [1, 2, 3]
# b    [4, 5, 6]
# Name: matrix, dtype: object

# 0    1
# 1    2
# 2    3
# dtype: int64

# 1    4
# 2    5
# 3    6
# dtype: int64

# 0    [1, 2, 3]
# 1    [4, 5, 6]
# dtype: object

print(a.values, a.index, a.shape, a['a'], sep='\n\n')
# [list([1, 2, 3]) list([4, 5, 6])]
# Index(['a', 'b'], dtype='object')
# (2,)
# [1, 2, 3]
2.2.2 DataFrame

   DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等)。DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共同用一个索引)。

DataFrame 函数如下:pd.DataFrame(data,index,columns,dtype,copy)

  • index:行标签/行索引;
  • columns:列标签/列索引;
  • dtype:数据类型;
  • copy:拷贝数据,默认为 False;

dir(pd.DataFrame):查看DataFrame的相关属性/函数

import numpy as np
import pandas as pd 

x = [[1,2,3],[4,5,6]]

'''  data:是列表 '''
a = pd.DataFrame(x, index=['a','b'], columns=['A','B','C'], copy=False)
print(a, end='\n\n')

''' data:是数组,数组是一维/二维的 '''
b = pd.DataFrame(np.array(x))
print(b, end='\n\n')

''' data:是字典 '''
print(pd.DataFrame(dict(enumerate(x))), sep='\n\n')

# 运行结果
#    A  B  C
# a  1  2  3
# b  4  5  6

#    0  1  2
# 0  1  2  3
# 1  4  5  6

#    0  1
# 0  1  4
# 1  2  5
# 2  3  6

print(a.values, a.index, a.columns, a.shape, sep='\n\n')
# [[1 2 3]
#  [4 5 6]]
# Index(['a', 'b'], dtype='object')
# Index(['A', 'B', 'C'], dtype='object')
# (2, 3)

2.3 常用基本函数

在这里插入图片描述在这里插入图片描述

2.4 窗口函数

   pandas中有3类窗口,分别是滚动窗口rolling、扩张窗口expanding以及指数加权窗口ewm。
在这里插入图片描述

2.4.1 滚动窗口

   要使用滑窗函数(即滚动窗口),就必须先要对一个序列使用.rolling得到滑窗对象,其最重要的参数为窗口大小window。
   在得到了滑窗对象后,能够使用相应的聚合函数进行计算,需要注意的是窗口包含当前行所在的元素,例如在第四个位置进行均值运算时,应当计算(2+3+4)/3,而不是(1+2+3)/3。

import pandas as pd 
a = pd.DataFrame([[4,6,9],[3,4,5]], columns=['A', 'B','C'])
rol = a.rolling(1)
print(a, rol, sep='\n\n')

# >>    A  B  C
# >> 0  4  6  9
# >> 1  3  4  5

# >> Rolling [window=1,center=False,axis=0,method=single]
2.4.2 扩张窗口

   扩张窗口又称累计窗口,可以理解为一个动态长度的窗口,其窗口的大小就是从序列开始处到具体操作的对应位置,其使用的聚合函数会作用于这些逐步扩张的窗口上。具体地说,设序列为a1, a2, a3, a4,则其每个位置对应的窗口即[a1]、[a1, a2]、[a1, a2, a3]、[a1, a2, a3, a4]。

rol = a.expanding()
print(rol)
# >> Expanding [min_periods=1,center=False,axis=0,method=single]
2.4.3 指数加权窗口
rol = a.ewm(com=0.5)
print(rol)
# >> ExponentialMovingWindow [com=0.5,min_periods=1,adjust=True,ignore_na=False,axis=0,method=single]

2.5 练习

2.5.1 口袋妖怪数据集

现有一份口袋妖怪的数据集点此下载,下面进行一些背景说明:

  • #代表全国图鉴编号,不同行存在相同数字则表示为该妖怪的不同状态;
  • 妖怪具有单属性和双属性两种,对于单属性的妖怪,Type 2为缺失值;
  • Total、HP、Attack、Defense、Sp.Atk、Sp.Def、Speed,分别代表:种族值、体力、物攻、防御、特攻、特防、速度,其中种族值为后6项之和;

问题:
1.  对HP、Attack、Defense、Sp.Atk、Sp.Def、Speed进行加总,验证是否为Total值;

import pandas as pd 
df = pd.read_csv('/XXXXX/Desktop/data/口袋妖怪.csv',encoding='Windows-1252')

# 获取多列,以列表形式表达,有2个[[]]
# 新增一列用 df['xxx'] ;若在原数据修改,用 df['xxx']或df.xxx 都行
df['total_new'] = df[['HP', 'Attack', 'Defense','Sp.Atk', 'Sp.Def', 'Speed']].sum(axis=1)

# 1.对HP···Speed加总,验证是否为Total值 
if (df.Total != df.total_new).sum() ==0:
    print('ans1:Total值没问题')
else:
    print('ans1:Total值有问题')

# >> ans1:Total值没问题

2.  对于#重复的妖怪只保留第一条记录,解决以下问题:
  2.1 求第一属性的种类数量和前三多数量对应的种类
  2.2 求第一属性和第二属性的组合种类

# 删除#重复的数据且只保留第一条记录
df_drop = df.drop_duplicates('#',keep='first')
del df_drop['total_new'] # 删除某列

# 2.1 第一属性的种类数量和前三多数量对应的种类
print('第一属性的种类数量:{}\n'.format(df_drop['Type1'].nunique()))
print('前三多数量对应的种类:\n{}\n'.format(df_drop['Type1'].value_counts().head(3)))

''' df_drop['Type1'].value_counts().head(3)
   等价于 
   df_drop.value_counts('Type1').head(3) '''

# >> 第一属性的种类数量:18
# >> 前三多数量对应的种类:
# >> Water     105
# >> Normal     93
# >> Grass      66
# >> Name: Type1, dtype: int64

# 2.2 第一属性和第二属性的组合种类
df_drop[['Type1','Type2']].drop_duplicates().shape[0]
# >> 143

3.  按照下述要求,构造Series:
  3.1 取出物攻,超过120的替换为high,不足50的替换为low,否则设为mid
  3.2 取出第一属性,分别用replace和apply替换所有字母为大写
  3.3 求每个妖怪六项能力的离差,即所有能力中偏离中位数最大的值,添加到df并从大到小排序

# 3.1 取出物攻,超过120的替换为high,不足50的替换为low,否则设为mid
# 方法一
df_drop['Attack'].mask(df_drop.Attack>120,'high').mask(df_drop.Attack<50,'low').mask(((df_drop.Attack>=50)&(df_drop.Attack<=120)),'mid').unique()
# 方法二
df_drop['Attack'].where(df_drop.Attack<=120,'high').where(df_drop.Attack>=50,'low').where((df_drop.Attack<50)|(df_drop.Attack>120),'mid').unique()

# 3.2 取出第一属性,分别用replace和apply替换所有字母为大写
df_drop.Type1.apply(lambda x : x.upper())
df_drop['Type1'].replace([i for i in df_drop['Type1']],  [i.upper() for i in df_drop['Type1']])
df_drop['Type1'].replace( { i:str.upper(i)  for i in df_drop['Type1'] } )
df_drop['Type1'].replace( { i:str.upper(i)  for i in df_drop['Type1'].unique() } )

# 3.3 求每个妖怪六项能力的离差,即所有能力中偏离中位数最大的值,添加到df并从大到小排序
df['deviation'] = (df[['HP', 'Attack', 'Defense','Sp.Atk', 'Sp.Def', 'Speed']].apply(lambda x : (x - x.median()).abs())).max(axis=1)
df.sort_values('deviation', ascending=False)
2.5.2 复习小知识
2.5.2.1 获取文件在电脑中的地址

   以Mac为例,打开‘终端’ ➔ 把需要的文件拖到终端窗口中 ➔ 松开鼠标 ➔ 就能获得地址

2.5.2.2 获取文件在电脑中的编码方式

   详见此链接文章中16.1 打开文件版块

import chardet
f = open('文件路径', 'rb')    # 以二进制模式读取文件
data =f.read()              # 获取文件内容
print(chardet.detect(data)) # 检测文件内容
# >> {'encoding': 'GB2312', 'confidence': 0.99, 'language': 'Chinese'}
2.5.2.3 numpy和pandas中的where的区别

numpy和pandas中的where的用法是相反的

np.where(condition[,x,y])

  • 满⾜条件(condition),输出x,不满⾜输出y。
  • 只有条件 (condition),没有x和y,则输出满⾜条件的元素的索引(类似于numpy.nonzero)。

a.where(cond, other,···)

  • a是Series或DataFrame
  • 如:a.where(a>10,‘low’)
  • 满足条件,输出a,不满足输出low

a.mask(cond, other,···)

  • a是Series或DataFrame
  • 如:a.mask(a>10,‘low’)
  • 满足条件,输出low,不满足输出a

谢谢大家🌹

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值