import numpy as np
import pandas as pd
一、文件的读取和写入
1. 文件读取
pandas读取csv,excel,txt时句子差不多,只要替换相应的csv,excel,txt为所需要读取的文件的格式即可
df_csv = pd.read_csv('data/my_csv.csv')
df_txt = pd.read_table('data/my_table.txt')
df_excel = pd.read_excel('data/my_excel.xlsx')
其中, header=None 表示第一行不作为列名, index_col 表示把某一列或几列作为索引, usecols 表示读取列的集合,默认读取所有的列, parse_dates 表示需要转化为时间的列,nrows 表示读取的数据行数。
在使用 read_table 的时候需要注意,参数 sep 中使用的是正则表达式,因此需要对 | 进行转义变成 | ,否则无法读取到正确的结果。
pd.read_table('data/my_table_special_sep.txt',
sep=' \|\|\|\| ', engine='python')
2 数据写入
df_txt.to_csv('data/my_txt_saved.txt', sep='\t', index=False)
df_excel.to_excel('data/my_excel_saved.xlsx', index=False)
# pandas 中没有定义 to_table 函数,但是 to_csv 可以保存为 txt 文件,并且允许自定义分隔符,常用制表符 \t 分割:
df_txt.to_csv('data/my_txt_saved.txt', sep='\t', index=False)
如果想要把表格快速转换为 markdown 和 latex 语言,可以使用 to_markdown 和 to_latex 函数,此处需要安装 tabulate 包
print(df_csv.to_markdown())
| | col1 | col2 | col3 | col4 | col5 |
|---:|-------:|:-------|-------:|:-------|:---------|
| 0 | 2 | a | 1.4 | apple | 2020/1/1 |
| 1 | 3 | b | 3.4 | banana | 2020/1/2 |
| 2 | 6 | c | 2.5 | orange | 2020/1/5 |
| 3 | 5 | d | 3.2 | lemon | 2020/1/7 |
print(df_csv.to_latex())
\begin{tabular}{lrlrll}
\toprule
{} & col1 & col2 & col3 & col4 & col5 \\
\midrule
0 & 2 & a & 1.4 & apple & 2020/1/1 \\
1 & 3 & b & 3.4 & banana & 2020/1/2 \\
2 & 6 & c & 2.5 & orange & 2020/1/5 \\
3 & 5 & d & 3.2 & lemon & 2020/1/7 \\
\bottomrule
\end{tabular}
二、基本数据结构
numpy中常用的数据存储结构为array
pandas 中具有两种基本的数据存储结构,存储一维 values 的 Series 和存储二维 values 的 DataFrame
1.Series
s = pd.Series(data = [100, 'a', {'dic1':5}],
index = pd.Index(['id1', 20, 'third'], name='my_idx'),
dtype = 'object',
name = 'my_name')
s
利用 .shape 可以获取序列的长度:
s.shape
# (3,)
2. DataFrame
DataFrame 在 Series 的基础上增加了列索引,一个数据框可以由二维的 data 与行列索引来构造:
data = [[1, 'a', 1.2], [2, 'b', 2.2], [3, 'c', 3.2]]
df = pd.DataFrame(data=data,
index=['row_%d'%i for i in range(3)],
columns=[f'col_{i}' for i in range(3)])
df
上面的index也可以写为
index=[f’row_{i}’ for i in range(3)]
注意:在DataFrame中,可以由df[ ]得到相应的一个列组成的表,也可以由df[[ ]]得到由多个列组成的表
通过 .T 可以把 DataFrame 进行转置
常用函数
1.汇总函数
head, tail 函数分别表示返回表或者序列的前 n 行和后 n 行,其中 n 默认为5;info, describe 分别返回表的 信息概况 和表中 数值列对应的主要统计量。
2. 特征统计函数
在 Series 和 DataFrame 上定义了许多统计函数,最常见的是 sum, mean, median, var, std, max, min 。
此外,需要介绍的是 quantile, count, idxmax 这三个函数,它们分别返回的是分位数、非缺失值个数、最大值对应的索引。
3. 唯一值函数
对序列使用 unique 和 nunique 可以分别得到其唯一值组成的列表和唯一值的个数。value_counts 可以得到唯一值和其对应出现的频数。
如果想要观察多个列组合的唯一值,可以使用 drop_duplicates 。其中的关键参数是 keep ,默认值 first 表示每个组合保留第一次出现的所在行, last 表示保留最后一次出现的所在行, False 表示把所有重复组合所在的行剔除。
4. 替换函数
replace
df['Gender'].replace({'Female':0, 'Male':1}).head()
#replace 还有一种特殊的方向替换,
#指定 method 参数为 ffill 则为用前面一个最近的未被替换的值进行替换,
#bfill 则使用后面最近的未被替换的值进行替换。
s = pd.Series(['a', 1, 'b', 2, 1, 1, 'a'])
s
#0 a
#1 1
#2 b
#3 2
#4 1
#5 1
#6 a
#dtype: object
s.replace([1,2],method='ffill')
#0 a
#1 a
#2 b
#3 b
#4 b
#5 b
#6 a
#dtype: object
逻辑替换包括了 where 和 mask ,这两个函数是完全对称的: where 函数在传入条件为 False 的对应行进行替换,而 mask 在传入条件为 True 的对应行进行替换,当不指定替换值时,替换为缺失值。
s = pd.Series([-1, 1.2345, 100, -50])
s.where(s<0)
#0 -1.0
#1 NaN
#2 NaN
#3 -50.0
#dtype: float640
s.mask(s<0)
#0 NaN
#1 1.2345
#2 100.0000
#3 NaN
#dtype: float64
s_condition= pd.Series([True,False,False,True],index=s.index)
s.mask(s_condition, -50)
#0 -50.0000
#1 1.2345
#2 100.0000
#3 -50.0000
#dtype: float64
注意:上面只能用布尔值Ture False表示而不能用对应的1 0哦!!!
数值替换包含了 round, abs, clip 方法,它们分别表示按照给定精度四舍五入、取绝对值和截断。在 clip 中,超过边界的只能截断为边界值
如何把超过边界值的设定为自定义的呢??[replace]
s = pd.Series([-1,1.2345,100,-50])
s.clip(0,2).replace({2:'xixi'})
5. 排序函数
排序共有两种方式,其一为值排序,其二为索引排序,对应的函数是 sort_values 和 sort_index 。
6. apply方法
df.apply(函数f)
对df中每个元素都作用函数f
五、练习
Ex1:口袋妖怪数据集
现有一份口袋妖怪的数据集,下面进行一些背景说明:
-
#代表全国图鉴编号,不同行存在相同数字则表示为该妖怪的不同状态
-
妖怪具有单属性和双属性两种,对于单属性的妖怪, Type 2 为缺失值
-
Total, HP, Attack, Defense, Sp. Atk, Sp. Def, Speed 分别代表种族值、体力、物攻、防御、特攻、特防、速度,其中种族值为后6项之和
df = pd.read_csv('Pokemon.csv')
df.head(3)
- 对 HP, Attack, Defense, Sp. Atk, Sp. Def, Speed 进行加总,验证是否为 Total 值。
#1
columns = df.columns[-6:]
df[columns].sum(axis=1)
2. 对于 # 重复的妖怪只保留第一条记录,解决以下问题
df['#'].drop_duplicates(keep='first', inplace=True)
a.求第一属性的种类数量和前三多数量对应的种类
#第一属性的种类数量
df['Type 1'].value_counts()
#前三多数量对应的种类
df['Type 1'].value_counts()[0:3].index
b. 求第一属性和第二属性的组合种类
把第一属性,第二属性当作索引!!!
df.set_index(['Type 1','Type 2']).index
c. 求尚未出现过的属性组合
所有的属性组合减去2b中出现的属性组合
all_kind=set()
for i in df['Type 1']:
for j in df['Type 2']:
all_kind.add((i,j))
appeared=df.set_index(['Type 1','Type 2']).index
tmp = set(appeared)
all_kind-tmp
#即可得到答案
可用数量关系验证答案
a= len(all_kind-tmp)
print(a, len(all_kind), len(tmp))
#188 342 154
- 按照下述要求,构造 Series :
a. 取出物攻,超过120的替换为 high ,不足50的替换为 low ,否则设为 mid
def set_attack(n):
if n>120:
return 'high'
elif n<50:
return 'low'
else:
return 'mid'
df['Attack'].apply(set_attack)
b.取出第一属性,分别用 replace 和 apply 替换所有字母为大写
# apply
t=df['Type 1']
t.apply(lambda x: x.upper())
# replace
t.replace([x for x in t], [x.upper() for x in t])
c.求每个妖怪六项能力的离差,即所有能力中偏离中位数最大的值,添加到 df 并从大到小排序
#要加.values转化为数组的形式才可以哦
df['licha'] = abs(df.iloc[:,-6:].values-df.iloc[:,-6:].median().values).max(axis=1)
df['licha'].sort_values(ascending=False)
参考
https://datawhalechina.github.io/joyful-pandas/build/html/%E7%9B%AE%E5%BD%95/ch2.html