CDA学习之Pandas - 常用函数和75个高频操作

目录

一、函数

1.1 常用函数

1.1.1 导⼊数据
pd.DataFrame() # 自己创建数据框,用于练习

pd.read_csv(filename) # 从CSV⽂件导⼊数据

pd.read_table(filename) # 从限定分隔符的⽂本⽂件导⼊数据

pd.read_excel(filename) # 从Excel⽂件导⼊数据

pd.read_sql(query,connection_object) # 从SQL表/库导⼊数据

pd.read_json(json_string) # 从JSON格式的字符串导⼊数据

pd.read_html(url) # 解析URL、字符串或者HTML⽂件,抽取其中的tables表格

1.1.2 导出数据
df.to_csv(filename) #导出数据到CSV⽂件

df.to_excel(filename) #导出数据到Excel⽂件

df.to_sql(table_name,connection_object) #导出数据到SQL表

df.to_json(filename) #以Json格式导出数据到⽂本⽂件

writer=pd.ExcelWriter('test.xlsx',index=False) 
df1.to_excel(writer,sheet_name='单位')和writer.save(),将多个数据帧写⼊同⼀个⼯作簿的多个sheet(⼯作表)

1.1.3 查看数据
df.head(n) # 查看DataFrame对象的前n⾏

df.tail(n) # 查看DataFrame对象的最后n⾏

df.shape() # 查看⾏数和列数

df.info() # 查看索引、数据类型和内存信息

df.columns() # 查看字段(⾸⾏)名称

df.describe() # 查看数值型列的汇总统计

s.value_counts(dropna=False) # 查看Series对象的唯⼀值和计数

df.apply(pd.Series.value_counts) # 查看DataFrame对象中每⼀列的唯⼀值和计数

df.isnull().any() # 查看是否有缺失值

df[df[column_name].duplicated()] # 查看column_name字段数据重复的数据信息

df[df[column_name].duplicated()].count() # 查看column_name字段数据重复的个数

1.1.4 数据选取
df[col] # 根据列名,并以Series的形式返回列

df[[col1,col2]] # 以DataFrame形式返回多列

s.iloc[0] # 按位置选取数据

s.loc['index_one'] # 按索引选取数据

df.iloc[0,:] # 返回第⼀⾏

df.iloc[0,0] # 返回第⼀列的第⼀个元素

df.loc[0,:] # 返回第⼀⾏(索引为默认的数字时,⽤法同df.iloc),但需要注意的是loc是按索引,iloc参数只接受数字参数

df.ix[[:5],["col1","col2"]] # 返回字段为col1和col2的前5条数据,可以理解为loc和
iloc的结合体。

df.at[5,"col1"] # 选择索引名称为5,字段名称为col1的数据

df.iat[5,0] # 选择索引排序为5,字段排序为0的数据

1.1.5 数据处理
df.columns= ['a','b','c'] # 重命名列名(需要将所有列名列出,否则会报错)

pd.isnull() # 检查DataFrame对象中的空值,并返回⼀个Boolean数组

pd.notnull() # 检查DataFrame对象中的⾮空值,并返回⼀个Boolean数组

df.dropna() # 删除所有包含空值的⾏

df.dropna(axis=1) # 删除所有包含空值的列

df.dropna(axis=1,thresh=n) # 删除所有⼩于n个⾮空值的⾏

df.fillna(value=x) # ⽤x替换DataFrame对象中所有的空值,⽀持

df[column_name].fillna(x)

s.astype(float) # 将Series中的数据类型更改为float类型

s.replace(1,'one') # ⽤‘one’代替所有等于1的值

s.replace([1,3],['one','three']) # ⽤'one'代替1,⽤'three'代替3

df.rename(columns=lambdax:x+1) # 批量更改列名

df.rename(columns={'old_name':'new_ name'}) # 选择性更改列名

df.set_index('column_one') # 将某个字段设为索引,可接受列表参数,即设置多个索引

df.reset_index("col1") # 将索引设置为col1字段,并将索引新设置为0,1,2...

df.rename(index=lambdax:x+1) # 批量重命名索引

1.1.6 数据分组和排序
df.sort_index().loc[:5] # 对前5条数据进⾏索引排序

df.sort_values(col1) # 按照列col1排序数据,默认升序排列

df.sort_values(col2,ascending=False) # 按照列col1降序排列数据

df.sort_values([col1,col2],ascending=[True,False]) # 先按列col1升序排列,后按col2降序排列数据

df.groupby(col) # 返回⼀个按列col进⾏分组的Groupby对象

df.groupby([col1,col2]) # 返回⼀个按多列进⾏分组的Groupby对象

df.groupby(col1)[col2].agg(mean) # 返回按列col1进⾏分组后,列col2的均值,agg可以接受列表参数,agg([len,np.mean])

df.pivot_table(index=col1,values=[col2,col3],aggfunc={col2:max,col3:[ma,min]}) # 创建⼀个按列col1进⾏分组,计算col2的最⼤值和col3的最⼤值、最⼩值的数据透视表

df.groupby(col1).agg(np.mean) # 返回按列col1分组的所有列的均值,⽀持

df.groupby(col1).col2.agg(['min','max'])

data.apply(np.mean) # 对DataFrame中的每⼀列应⽤函数np.mean

data.apply(np.max,axis=1) # 对DataFrame中的每⼀⾏应⽤函数np.max

df.groupby(col1).col2.transform("sum") # 通常与groupby连⽤,避免索引更改

1.1.7 数据合并
df1.append(df2) # 将df2中的⾏添加到df1的尾部

df.concat([df1,df2],axis=1,join='inner') # 将df2中的列添加到df1的尾部,值为空的对应⾏与对应列都不要

df1.join(df2.set_index(col1),on=col1,how='inner') # 对df1的列和df2的列执⾏SQL形式的join,默认按照索引来进⾏合并,如果df1和df2有共同字段时,会报错,可通过设置lsuffix,rsuffix来进⾏解决,如果需要按照共同列进⾏合并,就要⽤到set_index(col1)

pd.merge(df1,df2,on='col1',how='outer') # 对df1和df2合并,按照col1,⽅式为outer

pd.merge(df1,df2,left_index=True,right_index=True,how='outer') #与 df1.join(df2, how='outer')效果相同

1.1.8 数据显示
pd.set_option('display.max_rows', None)		#显示所有行
pd.set_option('display.max_columns', None) 	#显示所有列
pd.set_option('max_colwidth', None)			# 显示列中单独元素的最大长度
pd.set_option('expand_frame_repr',True) 	# True表示列可以换行显示。设置成False的时候不允许换行显示;
pd.set_option('display.width', 80) 			#横向最多显示多少个字符;

1.2 函数列表

整理了100个Pandas常用的函数,分别分为6类:统计汇总函数、数据清洗函数、数据筛选函数、绘图与元素级运算函数、时间序列函数和其他函数。

1.2.1 统计汇总函数
函数名功能参数及说明
min()计算最小值
max()计算最大值
sum()求和
mean()计算平均值
count()计数(统计非缺失元素的个数)
size()计数(统计所有元素的个数)
median()计算中位数
var()计算方差
std()计算标准差
quantile()计算任意分位数
cov()计算协方差
corr()计算相关系数
skew()计算偏度
kurt()计算峰度
mode()计算众数
describe()描述性统计(一次性返回多个统计结果)
groupby()分组
aggregate()聚合运算(可以自定义统计函数)
argmin()寻找最小值所在位置
argmax()寻找最大值所在位置
any()等价于逻辑“或”
all()等价于逻辑“与”
value_counts()频次统计
cumsum()运算累计和
cumprod()运算累计积
pct­­_change()运算比率(后一个元素与前一个元素的比率)
1.2.2 数据清洗函数
函数名功能参数及说明
duplicated()判断序列元素是否重复
drop_duplicates()删除重复值
hasnans()判断序列是否存在缺失(返回TRUE或FALSE)
isnull()判断序列元素是否为缺失(返回与序列长度一样的bool值)
notnull()判断序列元素是否不为缺失(返回与序列长度一样的bool值)
dropna()删除缺失值
fillna()缺失值填充
ffill()前向后填充缺失值(使用缺失值的前一个元素填充)
bfill()后向填充缺失值(使用缺失值的后一个元素填充)
dtypes()检查数据类型
astype()类型强制转换
pd.to_datetime转日期时间型
factorize()因子化转换
sample()抽样
where()基于条件判断的值替换
replace()按值替换(不可使用正则)
str.replace()按值替换(可使用正则)
str.split.str()字符分隔
1.2.3 数据筛选函数
函数名功能参数及说明
isin()成员关系判断
between()区间判断
loc()条件判断(可使用在数据框中)
iloc()索引判断(可使用在数据框中)
compress()条件判断
nlargest()搜寻最大的n个元素
nsmallest()搜寻最小的n个元素
str.findall()子串查询(可使用正则)
query查询函数格式:df.query(‘expression’)。示例:df.query(“brand in [‘Python数据之道’,‘价值前瞻’,‘菜鸟数据之道’] & A > 3 & B > 3”) 等同于:df[(df[‘brand’].isin([‘Python数据之道’,‘价值前瞻’,‘菜鸟数据之道’])) & (df[‘A’] > 3) & (df[‘B’] > 3)]
import pandas as pd
df = pd.DataFrame({'brand':['Python数据之道','价值前瞻','菜鸟数据之道','Python','Java'],  
    'A':[10,2,5,20,16], 
    'B':[4,6,8,12,10], 
    'C':[8,12,18,8,2], 
    'D':[6,18,14,6,12], 
    'till years':[4,1,1,30,30]})
df.query("brand in ['Python数据之道','价值前瞻','菜鸟数据之道'] & A > 3 & B > 3")
df[(df['brand'].isin(['Python数据之道','价值前瞻','菜鸟数据之道'])) & (df['A'] > 3) & (df['B'] > 3)]

在这里插入图片描述

1.2.4 绘图与元素级运算函数
函数名功能参数及说明
hist()绘制直方图
plot()可基于kind参数绘制更多图形(饼图,折线图,箱线图等)
map()元素映射
apply()基于自定义函数的元素级操作
1.2.5 时间序列函数
函数名功能参数及说明
dt.date()抽取出日期值
dt.time()抽取出时间(时分秒)
dt.year()抽取出年
dt.mouth()抽取出月
dt.day()抽取出日
dt.hour()抽取出时
dt.minute()抽取出分钟
dt.second()抽取出秒
dt.quarter()抽取出季度
dt.weekday()抽取出星期几(返回数值型)
dt.weekday_name()抽取出星期几(返回字符型)
dt.week()抽取出年中的第几周
dt.dayofyear()抽取出年中的第几天
dt.daysinmonth()抽取出月对应的最大天数
dt.is_month_start()判断日期是否为当月的第一天
dt.is_month_end()判断日期是否为当月的最后一天
dt.is_quarter_start()判断日期是否为当季度的第一天
dt.is_quarter_end()判断日期是否为当季度的最后一天
dt.is_year_start()判断日期是否为当年的第一天
dt.is_year_end()判断日期是否为当年的最后一天
dt.is_leap_year()判断日期是否为闰年
1.2.6 其他函数
函数名功能参数及说明
append()序列元素的追加(需指定其他序列)
diff()一阶差分
round()元素的四舍五入
sort_values()按值排序
sort_index()按索引排序
to_dict()转为字典
tolist()转为列表
unique()元素排重

二、75个高频操作

目录

1、pandas导入、查看版本
2、使用python list、python dict、numpy.ndarray创建pandas.Series
3、将pandas.Series转化为pandas.DataFrame
4、将多个pandas.Series合并为一个pandas.DataFrame
5、修改pandas.Series index名称
6、pandas.Series1移除pandas.Series1中和pandas.Series2共同的部分
7、求pandas.Series1和pandas.Series2的交集、并集、差集
8、求pandas.Series分位数(最小值、1/4分位数、中位数、3/4分位数、最大值)
9、求pandas.Series()频数
10、输出pandas.Series()中频数排第一二位的、其它的替换为other
11、将pandas.Series()均分为10个区间、每个值使用区间名称标记
12、将pandas.Series()转换为指定shape的pandas.DataFrame
13、取出pandas.Series()中满足条件数据的位置index
14、取出pandas.Series()指定位置的数据
15、pandas.Series()水平、垂直合并
16、输出pandas.Series()子集的index号
17、求真实和预测pd.Series之间的均方误差损失函数(MSE,mean squared error)
18、pd.Series字符串型数据首字母大写转换
19、pd.Series字符串型数据字符长度计算
20、pd.Series中两两数之间差异
21、pd.Series中日期字符串转换为datetime格式
22、获取pd.Series日期字符串中时间对象
23、pd.Series日期字符串中修改为按指定日期输出
24、输出pd.Series中至少包含两个元音字符的数据
25、输出pd.Series中有效的email地址
26、pd.Series1按pd.Series2分组并求均值
27、计算两个pd.Series之间的欧式距离
28、求pd.Series局部峰值index
29、pd.Series字符串数据中使用最低频字符填充空格
30、创建时间序列数据,赋予随机值
31、缺省的时间序列值 不同方式填充
32、找出pd.Series中自相关性最大的数据
33、从一个csv 文件中每间隔50行取数据生成pandas.DataFrame
34、从一个csv 文件取数据生成pandas.DataFrame(新增加一分类列)
35、生成一个按规定步长平移的pandas.DataFrame
36、从一个csv 文件读取指定列生成pandas.DataFrame
37、输出DataFrame的行数、列数、数据类型、类型频数、Series转list
38、输出满足某个规则的DataFrame数据行和列号
39、修改DataFrame的列名称
40、DataFrame中是否有缺省值确认
41、DataFrame中缺省值统计
42、各自列均值填充DataFrame中各自列缺省值
43、各自列均值、中值填充DataFrame中各自列缺省值(使用apply)
44、从DataFrame选择子DataFrame
45、 改变DataFrame列顺序
46、大DataFrame修改默认显示的行和列数
47、DataFrame数据小数位数设置
48、 DataFrame数据小数转百分比显示
49、DataFrame数据每隔20行读取
50、创建DataFrame主键
51、获取DataFrame某一列中第n大的值索引
52、获取DataFrame某一列中第n大的值大于指定值得索引
53、获取DataFrame中行和大于100的行
54、 Series or DataFrame中使用分位数填充超限区域
55、去除指定值将DataFrame转换为最大方阵
56、DataFrame两行交换
57、DataFrame逆序输出
58、DataFrame转对角矩阵
59、DataFrame那一列含有最多行最大值
60、DataFrame创建新列:每行为行号(按欧几里得距离而来)
61、求DataFrame各列之间最大相关系数
62、DataFrame创建一列:包含每行中最小值与最大值比值
63、DataFrame创建一列:包含每行中第二大的值
64、DataFrame每列按特定方式归一化
65、计算DataFrame每行与后一行的相关系数
66、DataFrame对角线元素替换为0
67、DataFrame按某列分组、提取某个分组
68、DataFrame按另外列分组、提取当前列中指定值(看下方例子,需求不好描述)
69、DataFrame分组(看下方例子,需求不好描述)
70、两个DataFrame使用类似SQL 中INNER JOIN拼接
71、移除DataFrame1中在DataFrame2出现的行
72、取出DataFrame中两列值相等的行号
73、DataFrame中新建两列:滞后列和提前列(看下方例子,需求BT)
74、DataFrame中所有值出现频次统计
75、拆分DataFrame中某列文本为两列

2.1、pandas导入、查看版本

#pandas导入
import pandas as pd

#pandas输出版本信息
print(pd.__version__)

#pandas输出详细版本信息、 Python版本、相关程序包、操作系统等信息以json格式输出
print(pd.show_versions(as_json=True))

#pandas输出相关信息以默认格式输出
print(pd.show_versions())

在这里插入图片描述

2.2、使用python list、python dict、numpy.ndarray创建pandas.Series

# 2、使用python list、python dict、numpy.ndarray创建pandas.Series
import pandas as pd
import numpy as np
mylist = list('abcedfghijklmnopqrstuvwxyz')     # python list
myarr = np.arange(26)                           #numpy.ndarray
mydict = dict(zip(mylist, myarr))               #python dict

ser1 = pd.Series(mylist)
ser2 = pd.Series(myarr)
ser3 = pd.Series(mydict)
print(ser1.head(3))
print(ser2.head(3))
print(ser3.head(3))

在这里插入图片描述

2.3、将pandas.Series转化为pandas.DataFrame

# 3、将pandas.Series转化为pandas.DataFrame
mylist = list('abcedfghijklmnopqrstuvwxyz')
myarr = np.arange(26)
mydict = dict(zip(mylist, myarr))
ser = pd.Series(mydict)

#to_frame()结合reset_index()使用
df = ser.to_frame().reset_index()
print(type(df))
print(df.head())

在这里插入图片描述

2.4、将多个pandas.Series合并为一个pandas.DataFrame

# 4、将多个pandas.Series合并为一个pandas.DataFrame
ser1 = pd.Series(list('abcedfghijklmnopqrstuvwxyz'))
ser2 = pd.Series(np.arange(26))

# 解决方法1
df = pd.concat([ser1, ser2], axis=1)
print('1-------------')
print(df.head())

# 解决方法2
df = pd.DataFrame({'col1': ser1, 'col2': ser2})
print('2-------------')
print(df.head())

在这里插入图片描述

2.5、修改pandas.Series index名称

# 5、修改pandas.Series index名称
ser = pd.Series(list('abcedfghijklmnopqrstuvwxyz'))
print(ser.head(3))
print(f'原始Sersies index名称:{ser.name}')

ser.name = 'alphabets'
print(ser.head(3))
print(f'修改后Sersies index名称:{ser.name}')

在这里插入图片描述

2.6、pandas.Series1移除pandas.Series1中和pandas.Series2共同的部分

# 6、 pandas.Series1中移除pandas.Series1中和pandas.Series2共同的部分--差集
ser1 = pd.Series([1, 2, 3, 4, 5])
ser2 = pd.Series([4, 5, 6, 7, 8])

ser3 = ser1[~ser1.isin(ser2)]
print(ser3)

在这里插入图片描述

2.7、求pandas.Series1和pandas.Series2的交集、并集、差集

# 7、求pandas.Series1和pandas.Series2的交集、并集、差集
ser1 = pd.Series([1, 2, 3, 4, 5])
ser2 = pd.Series([4, 5, 6, 7, 8])

ser_i = pd.Series(np.intersect1d(ser1, ser2))   # intersect 交集
ser_u = pd.Series(np.union1d(ser1, ser2))       # union 并集
ser_s = ser_u[~ser_u.isin(ser_i)]               # Subtraction 差集

print("交集-------")
print(ser_i)

print("并集-------")
print(ser_u)

print("差集-------")
print(ser_s)

在这里插入图片描述

2.8、求pandas.Series分位数(最小值、1/4分位数、中位数、3/4分位数、最大值)

# 8、求pandas.Series分位数(最小值、1/4分位数、中位数、3/4分位数、最大值)
state = np.random.RandomState(100)
ser = pd.Series(state.normal(10, 5, 25))

print(ser)
print(np.percentile(ser, q=[0, 25, 50, 75, 100]))#可是设置其它任何想输出的分位数

在这里插入图片描述

2.9、求pandas.Series()频数

# 9、求pandas.Series()频数
# numpy.take(arr,indices,axis = None,out = None,mode ='raise') # 沿轴取数组中的元素。
# pd.Series([list],index=[list]) 参数为list ,index为可选参数,若不填写则默认为index从0开始
arr = list('abcdefgh')                  # 源数组
indices = np.random.randint(8, size=30) # 取索引值为0-7随机整数的30个元素,组成一个源数组索引值的数组
ser = pd.Series(np.take(arr, indices))  # 从8个元素的源数组中按索引值数组(列表)随机取30个元素,组成Series
print(ser)
print(ser.value_counts())   # 求频数

在这里插入图片描述

2.10、输出pandas.Series()中频数排第一二位的、其它的替换为other

# 10、输出pandas.Series()中频数排第一二位的、其它的替换为other
ser = pd.Series(np.random.randint(1, 6, 12)) # 生成12个1-5的随机数,转换为Series
print(ser)
print(ser.value_counts())   # 输出统计结果
ser[~ser.isin(ser.value_counts().index[:2])] = 'Other' 
print(ser)

在这里插入图片描述

2.11、将pandas.Series()均分为10个区间、每个值使用区间名称标记

# 11、将pandas.Series()均分为10个区间、每个值使用区间名称标记
np.random.seed(666)  # 用固定的种子锁定随机结果,让结果可复现
ser = pd.Series(np.random.random(20))
print(ser)
ser_qcut = pd.qcut(ser,
        q=[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
        labels=['1st', '2nd', '3rd', '4th', '5th', '6th', '7th', '8th', '9th','10th']
        )
print(ser_qcut)

在这里插入图片描述

2.12、将pandas.Series()转换为指定shape的pandas.DataFrame

# 12、将pandas.Series()转换为指定shape的pandas.DataFrame
nums = np.random.randint(1, 10, 35)
ser = pd.Series(nums)
print(ser.values)
print(type(ser.values))
df1 = pd.DataFrame(ser.values.reshape(7,5))
df2 = pd.DataFrame(nums.reshape(7, 5))
print(df1)
print('--------------')
print(df2)

在这里插入图片描述

2.13、取出pandas.Series()中满足条件数据的位置index

# 13、取出pandas.Series()中满足条件数据的位置index
np.random.seed(666) 
ser = pd.Series(np.random.randint(1, 10, 15))
print(ser)
arr_i = np.argwhere(ser.values % 3 == 0)
print(type(arr_i)) # 数据为3的倍数的位置index
print(arr_i) # 数据为3的倍数的位置index
print([i for i in arr_i])
print([i[0] for i in arr_i])

在这里插入图片描述

2.14、取出pandas.Series()指定位置的数据

# 14、取出pandas.Series()指定位置的数据
ser = pd.Series(list('abcdefghijklmnopqrstuvwxyz'))
print(ser)
pos = [0, 4, 8, 14, 20]#待取出位置
print(ser.take(pos))

在这里插入图片描述

2.15、pandas.Series()水平、垂直合并

# 15、pandas.Series()水平、垂直合并
ser1 = pd.Series(range(5))
ser2 = pd.Series(list('abcde'))

# 垂直合并
ser3 = ser1.append(ser2)
print(ser3)
ser4 = pd.concat([ser1, ser2], axis=0)
print(ser4)

# 水平合并
df = pd.concat([ser1, ser2], axis=1)
print(df)

在这里插入图片描述

2.16、输出pandas.Series()子集的index号

# 16、输出pandas.Series()子集的index号
# 获取ser2在ser1中的index号
ser1 = pd.Series([10, 9, 6, 5, 3, 1, 12, 8, 13])
ser2 = pd.Series([1, 3, 10, 13])
# ser2 = pd.Series([1, 3, 10, 13, 18])
# 方法1
# 三个参数np.where(condition, x, y):满足条件(condition),输出x,不满足输出y。
# 一个参数np.where(condition):则输出满足条件 (即非0) 元素的坐标,坐标以tuple的形式给出
# condition条件可以使用广播
print(np.where(ser1 == ser2[0]))  # 结果为元组 (array([5], dtype=int64),)
print(np.where(ser1 == ser2[0])[0])  # 结果为数组 [5]
print([np.where(ser1 == i)[0] for i in ser2]) # [array([5], dtype=int64), array([4], dtype=int64), array([0], dtype=int64), array([8], dtype=int64)]
print([np.where(ser1 == i)[0][0] for i in ser2]) # [5, 4, 0, 8]
# 配合ser2 = pd.Series([1, 3, 10, 13, 18]),当指定值找不到用if的三元表达式
# print([np.where(ser1 == i)[0][0] if len(np.where(ser1 == i)[0])>0 else np.where(ser1 == i)[0] for i in ser2]) # [5, 4, 0, 8]

# 方法2
print([np.where(ser1 == i)[0].tolist()[0] for i in ser2]) # [5, 4, 0, 8]

# 方法3
# Pandas Index.get_loc()函数返回所指定值的索引位置,切片或布尔掩码。
print([pd.Index(ser1).get_loc(i) for i in ser2]) # [5, 4, 0, 8]

在这里插入图片描述

2.17、求真实和预测pd.Series之间的均方误差损失函数(MSE,mean squared error)

''' 17、求真实和预测pd.Series之间的均方误差损失函数(MSE,mean squared error) '''
truth = pd.Series(range(10))
pred = pd.Series(range(10)) + np.random.random(10)
print(np.mean((truth-pred)**2))

在这里插入图片描述

2.18、pd.Series字符串型数据首字母大写转换

''' 18、pd.Series字符串型数据首字母大写转换 '''
ser = pd.Series(['how', 'to', 'kick', 'ass?'])
# 方法一title()结合title()
print(ser.map(lambda x: x.title()))
# 方法二upper()结合lambda
print(ser.map(lambda x: x[0].upper() + x[1:]))
# 方法三title()结合列表推导式
print(pd.Series([i.title() for i in ser]))
'''Series中的map()函数可以接受一个函数或含有映射关系的字典型对象,使用map()是一种实现元素级转换以及其他数据清理工作的便捷方式。(DataFrame中的对应的是applymap()函数以及apply()---对每一行操作,等同于axis=0)'''
data = pd.DataFrame({'food':['bacon','pulled pork','bacon','Pastrami','corned beef','Bacon','pastrami','honey ham','nova lox'],
                  'ounces':[4,3,12,6,7.5,8,3,5,6]})
print(data)
meat_to_animal = {
    'bacon':'pig',
    'pulled pork':'pig',
    'pastrami':'cow',
    'corned beef':'cow',
    'honey ham':'pig',
    'nova lox':'salmon'    }  
data['animal'] = data['food'].map(str.lower).map(meat_to_animal) 
print(data) 

在这里插入图片描述

2.19、pd.Series字符串型数据字符长度计算

''' 19、pd.Series字符串型数据字符长度计算 '''
ser1 = pd.Series(['how', 'to', 'kick', 'ass?'])
print(ser1)
ser2 = ser1.map(lambda x: len(x))
print(ser2)
print(type(ser2))

在这里插入图片描述

2.20、pd.Series中两两数之间差异

''' 20、pd.Series中两两数之间差异 '''
ser = pd.Series([1, 3, 6, 10, 15, 21, 27, 35])
print(ser.diff().tolist())

在这里插入图片描述

2.21、pd.Series中日期字符串转换为datetime格式

''' 21、pd.Series中日期字符串转换为datetime格式 '''
ser = pd.Series(['01 Jan 2010', '02-02-2011', '20120303', '2013/04/04', '2014-05-05', '2015-06-06T12:20'])
print(ser)
# 方法一
from dateutil.parser import parse  # 与日期相关库里的一个日期解析器,能够将字符串转换为日期格式
print(ser.map(lambda x: parse(x)))
# 方法二
print(pd.to_datetime(ser))

在这里插入图片描述

2.22、获取pd.Series日期字符串中时间对象

''' 22、获取pd.Series日期字符串中时间对象 '''
ser = pd.Series(['01 Jan 2011', '02-02-2011', '20120303', '2013/04/04', '2014-05-05', '2015-06-06T12:20'])
print(ser)
from dateutil.parser import parse
ser_ts = ser.map(lambda x: parse(x))    # 转为pd标准日期时间格式
print(ser_ts)
# 处于该月中的第几天
print("Date: ", ser_ts.dt.day.tolist())
# 处于该年的第几天
print("Day number of year: ", ser_ts.dt.dayofyear.tolist())
# 处于该年的第几周
print("Week number: ", ser_ts.dt.isocalendar().week)
# isocalendar数据框
print("df_isocalendar: ", ser_ts.dt.isocalendar())
# 周几
print("Day of week: ", ser_ts.dt.day_name().tolist())

在这里插入图片描述

2.23、pd.Series日期字符串中修改为按指定日期输出

''' 23、pd.Series日期字符串中修改为按指定日期输出 '''
ser = pd.Series(['Jan 2010', 'Feb 2011', 'Mar 2012'])
# 方法1
print(pd.to_datetime(ser))          # 给定年月,日默认1
from dateutil.parser import parse
# Parse the date
ser_ts = ser.map(lambda x: parse(x))# 给定年月,日默认为当前系统日期中的日
print(ser_ts)
# Construct date string with date as 4
ser_datestr = ser_ts.dt.year.astype('str') + '-' + ser_ts.dt.month.astype('str') + '-' + '04'
print(ser_datestr)
# Format it.
print('~~~~~~~~~~~~~', [parse(i).strftime('%Y-%m-%d') for i in ser_datestr])
# 方法2
print(ser.map(lambda x: parse('04' + x)))   # 日 + 给定年月
print(ser.map(lambda x: parse(x + '55')))   # 给定年月,日默认为当前系统日期中的日,加数为秒

在这里插入图片描述

2.24、输出pd.Series中至少包含两个元音字符的数据

''' 24、输出pd.Series中至少包含两个元音字符的数据 '''
ser = pd.Series(['Apple', 'Orange', 'Plan', 'Python', 'Money'])
from collections import Counter
print(ser.map(lambda x: [Counter(x.lower()).get(i, 0) for i in list('aeiou')]))
mask = ser.map(lambda x: sum([Counter(x.lower()).get(i, 0) for i in list('aeiou')]) >= 2)
print('apple中每个字母的次数:', Counter('Apple'.lower()))      # Counter({'p': 2, 'a': 1, 'l': 1, 'e': 1})
print('计数器类型:', type(Counter('Apple'.lower())))          # <class 'collections.Counter'> 类似字典
print('查找计数器中字母a的个数:', Counter('Apple'.lower()).get('a', 0))     # 找不到,默认返回0
print('查找计数器中字母i的个数:', Counter('Apple'.lower()).get('i', 0))     # 找不到,默认返回0
print(mask)         
print(ser[mask])

在这里插入图片描述

2.25、输出pd.Series中有效的email地址

''' 25、输出pd.Series中有效的email地址 '''
# 三种方法
emails = pd.Series(['buying books at amazom.com', 'rameses@egypt.com', 'matt@t.co', 'narendra@modi.com'])
# Solution 1 (as series of strings)
import re
pattern ='[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}'
mask = emails.map(lambda x: bool(re.match(pattern, x)))
print(emails[mask])
# Solution 2 (as series of list)
print(emails.str.findall(pattern, flags=re.IGNORECASE))
# Solution 3 (as list)
print([x[0] for x in [re.findall(pattern, email) for email in emails] if len(x) > 0])

在这里插入图片描述

2.26、pd.Series1按pd.Series2分组并求均值

''' 26、pd.Series1按pd.Series2分组并求均值 
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)  主要用来创建等差数列。
start:返回样本数据开始点,stop:返回样本数据结束点,num:生成的样本数据量,默认为50,endpoint:True则包含stop;False则不包含stop
retstep:如果为True则结果会给出数据间隔,dtype:输出数组类型,axis:0(默认)或-1
'''
fruit = pd.Series(np.random.choice(['apple', 'banana', 'carrot'], 10))  # 从已有列表随机选择10个元素组成Series
weights = pd.Series(np.linspace(1, 10, 10))     # 创建1-10的浮点数series
weights1 = pd.Series(list(range(1,11)))         # 创建1-10的整数series
print(weights.groupby(fruit).mean())        # 重量按水果种类分组并求各组水果重量的平均值

在这里插入图片描述

2.27、计算两个pd.Series之间的欧式距离

欧式距离也称欧几里得距离,是最常见的距离度量,衡量的是多维空间中两个点之间的绝对距离。
也可以理解为:m维空间中两个点之间的真实距离,或者向量的自然长度(即该点到原点的距离)。在二维和三维空间中的欧氏距离就是两点之间的实际距离。计算公式:
在这里插入图片描述

''' 27、计算两个pd.Series之间的欧式距离 : 矩阵元素平方和,再开根号
np.linalg.norm(x, ord=None, axis=None, keepdims=False)  # 求范数
①x: 表示矩阵(也可以是一维);②ord:范数类型,ord=None:默认情况下,是求整体的矩阵元素平方和,再开根号。
ord=2-2范数,求特征值,然后求最大特征值得算术平方根;ord=1-1范数,求列和的最大值;ord=np.inf无穷范数,求行和的最大值;
'''
p = pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
q = pd.Series([10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
# 方法1 
print('欧式距离:', sum((p - q)**2)**.5)
# 方法2
print("默认参数(矩阵整体元素平方和开根号,不保留矩阵二维特性):", np.linalg.norm(p-q))

在这里插入图片描述

2.28、求pd.Series局部峰值index

''' 28、求pd.Series局部峰值index 
numpy.diff(a, n=1,axis=-1),沿着指定轴计算第N维的离散差值,后一个元素减去前一个元素,a:输入矩阵,n:可选,代表要执行几次差值,axis:默认是最后一个
np.sign(x),取数字x的符号(数字前的正负号),x>0返回1,x<0返回-1,x=0返回0
'''
ser = pd.Series([2, 10, 3, 4, 9, 10, 2, 7, 3])
print(np.diff(ser))                     # [ 8 -7  1  5  1 -8  5 -4]  后-前
print(np.sign(np.diff(ser)))            # [ 1 -1  1  1  1 -1  1 -1]  只保留符号
dd = np.diff(np.sign(np.diff(ser)))     #                            找到前后差值正负变换点,也就是曲线的拐点
print(dd)                               # [-2  2  0  0 -2  2 -2]
peak_locs = np.where(dd == -2)[0] + 1
print(peak_locs)                        # [1 5 7]

在这里插入图片描述

2.29、pd.Series字符串数据中使用最低频字符填充空格

''' 29、pd.Series字符串数据中使用最低频字符填充空格 '''
ser = pd.Series(list('dbc deb abed gade'))
freq = ser.value_counts()
print(freq)
print(freq.index)
least_freq = freq.index[-1]
str = "".join(ser.replace(' ', least_freq))
print(str)

在这里插入图片描述

2.30、创建时间序列数据,赋予随机值

''' 30、创建时间序列数据,赋予随机值 
pandas.date_range(start=None, end=None, periods=None, freq='D', tz=None, normalize=False, name=None, closed=None, **kwargs)
该函数主要用于生成一个固定频率的时间索引,在调用构造方法时,必须指定start、end、periods中的两个参数值,否则报错。
主要参数说明:
periods:固定时期,取值为整数或None
freq:日期偏移量,取值为string或DateOffset,默认为'D',
    默认freq = 'D':每日历日,B:每工作日,H:每小时,T/MIN:每分,S:每秒,L:每毫秒(千分之一秒),U:每微秒(百万分之一秒)
    freq = 'W-MON':每周从指定星期几开始算起,这里是周一。星期几缩写:MON/TUE/WED/THU/FRI/SAT/SUN
    freq = 'WOM-2MON':每月的第几个星期几开始算,这里是每月第二个星期一
    freq = 'M':M:每月最后一个日历日;Q-月:指定月为季度末,每个季度末最后一月的最后一个日历日;A-月:每年指定月份的最后一个日历日
            月缩写:JAN/FEB/MAR/APR/MAY/JUN/JUL/AUG/SEP/OCT/NOV/DEC;所以Q-月只有三种情况:1-4-7-10,2-5-8-11,3-6-9-12
    freq = 'BM':BM:每月最后一个工作日;BQ-月:指定月为季度末,每个季度末最后一月的最后一个工作日;BA-月:每年指定月份的最后一个工作日
    freq = 'MS':M:每月第一个日历日;Q-月:指定月为季度末,每个季度末最后一月的第一个日历日;A-月:每年指定月份的第一个日历日
    freq = 'BMS':BM:每月第一个工作日;BQ-月:指定月为季度末,每个季度末最后一月的第一个工作日;BA-月:每年指定月份的第一个工作日
    freq = '7D':7天
    freq = '2h30min':2小时30分钟
    freq = '2M':2月,每月最后一个日历日
normalize:若参数为True表示将start、end参数值正则化到午夜时间戳
name:生成时间索引对象的名称,取值为string或None
closed:可以理解成在closed=None情况下返回的结果中,若closed=‘left’表示在返回的结果基础上,再取左开右闭的结果,
        若closed='right'表示在返回的结果基础上,再取做闭右开的结果
'''
ser = pd.Series(np.random.randint(1,10,10), pd.date_range('2000-01-01', periods=10, freq='W-SAT'))
print(ser)

在这里插入图片描述

2.31、缺省的时间序列值 不同方式填充

''' 31、缺省的时间序列值 不同方式填充 
resample()是一个对常规时间序列数据重新采样和频率转换的便捷的方法,可以对原样本重新处理,
resample(rule,how=None,axis=0,fill_method=None,closed=None,label=None,convention=“start”,kind=None,loffset=None,limit=None,base=0,on=None,level=None)
    rule:表示重采样频率的字符串或DateOffset,比如D(天)、M(月)、5min(5分钟)、5D(5天)、2M(2个月)、60T(60分钟)等。
    how:用于产生聚合值的函数名或函数数组,默认为None。
    fill_method:表示升采样时如何插值,可以取值为fill、bfill或None,默认为None。
    closed:设置降采样哪一端是闭合的,可以取值为right或left。若设为right,则表示划分为左开右闭的区间;若设为left,则表示划分为左闭右开的区间。
    label:表示降采样时设置聚合值的标签。
    convention:重采样日期时,低频转高频采用的约定,可以取值为start或end,默认为start。
    limit:表示前向或后向填充时,允许填充的最大时期数。
    ser.resample('60T', base=30):base=30时,60分钟的时间间隔将移动30分钟
'''
ser = pd.Series([1,10,3, np.nan], index=pd.to_datetime(['2000-01-01', '2000-01-03', '2000-01-06', '2000-01-08']))
print(ser)
f_ser = ser.resample('D').ffill()  # 前填充
print(f_ser)
b_ser = ser.resample('D').bfill()  # 后填充
print(b_ser)
bf_ser = ser.resample('D').bfill().ffill()  # 先后填充,如后无值则前填充
print(bf_ser)

在这里插入图片描述

2.32、找出pd.Series中自相关性最大的数据

''' 32、找出pd.Series中自相关性最大的数据 
numpy.random.normal(loc=0,scale=1e-2,size=shape)  随机生成一个正态分布
    loc(float):正态分布的均值,对应着这个分布的中心。loc=0说明这一个以Y轴为对称轴的正态分布,
    scale(float):正态分布的标准差,对应分布的宽度,scale越大,正态分布的曲线越矮胖,scale越小,曲线越高瘦。
    size(int 或者整数元组):输出的值赋在shape里,默认为None。
Series.autocorr(lag=1)函数计算lag-N自相关,lag:执行自相关之前要应用的滞后次数。
np.abs(x)、np.fabs(x):计算数组各元素的绝对值
np.argmax(array, axis):用于返回一个numpy数组中最大值的索引值。
'''
ser = pd.Series(np.arange(20) + np.random.normal(1, 10, 20))
print(np.random.normal(1, 10, 20))
print(np.arange(20) + np.random.normal(1, 10, 20))
autocorrelations = [ser.autocorr(lag = i).round(2) for i in range(18)]
print(autocorrelations)
print('\n Lag 自相关性最大的位置: ', np.argmax(np.abs(autocorrelations[1:]))+1, '\n')

在这里插入图片描述

2.33、从一个csv 文件中每间隔50行取数据生成pandas.DataFrame

''' 33、从一个csv 文件中每间隔50行取数据生成pandas.DataFrame '''
# 方法1: 利用chunks分块和循环,这种方式可能造成数据列的排列顺序与原始数据不一致
df = pd.read_csv('datasets/BostonHousing.csv', chunksize=50)     # 分块读取csv超大文件,每块50行,生成分块df,此时并没有真正读取csv,只是定义了一个框架
df2 = pd.DataFrame()                        # 创建一个空的df2
for chunk in df:                            # 循环读取CSV,在同一个df中,每50行数据作为一组,不断覆盖写入,直至csv末尾
    df2 = df2.append(chunk.iloc[0,:])       # 把每个分块df的首行所有列追加到df2
print(df2.head(2))
# 方法2: 利用chunks分块和列表推导式
df = pd.read_csv('datasets/BostonHousing.csv', chunksize=50)
df3 = pd.concat([chunk.iloc[0] for chunk in df], axis=1)    # 纵向concat,每个series拼合到df2的最右侧
df3 = df3.transpose()   # 行列转置
print(df3.head(2))
# 方法3: Use csv reader
import csv          
with open('datasets/BostonHousing.csv', 'r') as f:
    reader = csv.reader(f)
    out = []
    for i, row in enumerate(reader):
        if i%50 == 0:                       # i只用于判断有没有读到数据
            out.append(row)
df4 = pd.DataFrame(out[1:], columns=out[0])
print(df4.head(2))

在这里插入图片描述

2.34、从一个csv 文件取数据生成pandas.DataFrame(新增加一分类列)

''' 34、从一个csv 文件取数据生成pandas.DataFrame(新增加一分类列) '''
##两种方式
# Solution 1: Using converter parameter
df = pd.read_csv('datasets/BostonHousing.csv', 
                 converters={'medv': lambda x: 'High' if float(x) > 25 else 'Low'}) # medv列大于25改为High,否则改为Low
print(df.head())
# Solution 2: Using csv reader
import csv
with open('datasets/BostonHousing.csv', 'r') as f:
    reader = csv.reader(f)
    out = []
    for i, row in enumerate(reader):
        if i > 0:
            row[13] = 'High' if float(row[13]) > 25 else 'Low'  # row[13]即为medv列
        out.append(row)
print(out[:3])          # out为二维数组,out[0]为表头,out[1:]为数据
df = pd.DataFrame(out[1:], columns=out[0])  # 利用二维数组第二行及以后的数据生成df,指定二维数组的第一行为列名
print(df.head())

在这里插入图片描述

2.35、生成一个按规定步长平移的pandas.DataFrame

''' 35、生成一个按规定步长平移的pandas.DataFrame '''
L = pd.Series(range(15))
def gen_strides(a, stride_len=5, window_len=5):
    n_strides = ((a.size-window_len)//stride_len) + 1
    return np.array([a[s:(s+window_len)] for s in np.arange(0, a.size, stride_len)[:n_strides]])
result = gen_strides(L, stride_len=2, window_len=4)
print(result)

在这里插入图片描述

2.36、从一个csv 文件读取指定列生成pandas.DataFrame

''' 36、从一个csv 文件读取指定列生成pandas.DataFrame '''
#usecols参数设置
df = pd.read_csv('https://raw.githubusercontent.com/selva86/datasets/master/BostonHousing.csv', usecols=['crim', 'medv'])
print(df.head())

在这里插入图片描述

2.37、输出DataFrame的行数、列数、数据类型、类型频数、Series转list

''' 37、输出DataFrame的行数、列数、数据类型、类型频数、Series转list '''
df = pd.read_csv('datasets/Cars93_miss.csv')
#  DataFrame的行数和列数
print(df.shape)                         # (93, 27)
# DataFrame各列数据类型
print(df.dtypes.head())
# 每种数据类型的频数
print(df.dtypes.value_counts())         # float64    18 , object      9
# DataFrame基础统计
print(df.describe())
# pd.Series转list 
print(df['Model'].tolist()[:5])    # ['Integra', 'Legend', '90', '100', '535i', ]

在这里插入图片描述

2.38、输出满足某个规则的DataFrame数据行和列号

''' 38、输出满足某个规则的DataFrame数据行和列号 
np.where(condition):只有条件 (condition),没有x和y,则输出满足条件 (即非0) 元素的坐标.
    坐标以tuple的形式给出,原数组有多少维,输出的tuple中就包含几个数组,分别对应符合条件元素的各维坐标。
'''
df = pd.read_csv('datasets/Cars93_miss.csv')
print(df)
#输出Price值最大时的行和列号
print(df.values == np.max(df.Price))
result = np.where(df.values == np.max(df.Price)) #df.values输出DataFrame的值,为numpy.ndarray类型
print(result)
row, col = np.where(df.values == np.max(df.Price)) #df.values输出DataFrame的值,为numpy.ndarray类型
print(f'\n 行号:{row},列号:{col} \n')
print((df.values == np.max(df.Price))[row[0]][col[0]])

在这里插入图片描述

2.39、修改DataFrame的列名称

''' 39、修改DataFrame的列名称 '''
#修改某一列的名称
df = pd.read_csv('datasets/Cars93_miss.csv')
print(df.columns)
df1=df.rename(columns = {'Type':'CarType'})
print(df1.columns)
# 或者
#df.columns.values[2] = "CarType"   # 限定了位置,如果df结构改变就乱套了,不要用

# map函数修改某一匹配的名称:此处将名称中的.替换为下划线
df.columns = df.columns.map(lambda x: x.replace('.', '_'))
print(df.columns)

在这里插入图片描述

2.40、DataFrame中是否有缺省值确认

''' 40、DataFrame中是否有缺失值确认 
DataFrame.any()与all():any()一个序列中满足一个True,则返回True;all()一个序列中所有值为True时,返回True
'''
df = pd.read_csv('datasets/Cars93_miss.csv')
print(df)
print(df.isnull())
print(df.isnull().values)
print(df.isnull().values.any())

在这里插入图片描述

2.41、DataFrame中缺省值统计

''' 41、DataFrame中缺省值统计 '''
df = pd.read_csv('datasets/Cars93_miss.csv')
n_missings_each_col = df.apply(lambda x: x.isnull().sum()) # 每列缺省值计数
print(n_missings_each_col)
print(n_missings_each_col.argmax()) # 缺省值数最多列的列号

在这里插入图片描述

2.42、各自列均值填充DataFrame中各自列缺省值

''' 42、各自列均值填充DataFrame中各自列缺省值 '''
df = pd.read_csv('datasets/Cars93_miss.csv')
df_out = df[['Min.Price', 'Max.Price']].apply(lambda x: x.fillna(x.mean()))
print(df_out.head())

在这里插入图片描述

2.43、各自列均值、中值填充DataFrame中各自列缺省值(使用apply)

''' 43、各自列均值、中值填充DataFrame中各自列缺省值(使用apply) '''
df = pd.read_csv('datasets/Cars93_miss.csv')
d = {'Min.Price': np.nanmean, 'Max.Price': np.nanmedian}
df[['Min.Price', 'Max.Price']] = df[['Min.Price', 'Max.Price']].apply(lambda x, d: x.fillna(d[x.name](x)), args=(d, ))
print(df[['Min.Price', 'Max.Price']])

在这里插入图片描述

2.44、从DataFrame选择子DataFrame

''' 44、从DataFrame选择子DataFrame '''
df = pd.DataFrame(np.arange(20).reshape(-1, 5), columns=list('abcde'))
# print(df)
# 选择子DataFrame
print(type(df[['a']]))          # <class 'pandas.core.frame.DataFrame'>
print(type(df.loc[:, ['a']]))   # <class 'pandas.core.frame.DataFrame'>
print(type(df.iloc[:, [0]]))    # <class 'pandas.core.frame.DataFrame'>

# 选择Series
print(type(df.a))
print(type(df['a']))
print(type(df.loc[:, 'a']))
print(type(df.iloc[:, 1]))

在这里插入图片描述

2.45、 改变DataFrame列顺序

''' 45、 改变DataFrame列顺序 '''
df = pd.DataFrame(np.arange(20).reshape(-1, 5), columns=list('abcde'))
# 方法1:传入一个list
df1= df[list('cbade')]
print(df1.head(2))
# 方法2:自定义函数
def switch_columns(df, col1=None, col2=None):
    colnames = df.columns.tolist()
    i1, i2 = colnames.index(col1), colnames.index(col2)
    colnames[i2], colnames[i1] = colnames[i1], colnames[i2]
    return df[colnames]
df2 = switch_columns(df, 'a', 'c')
print(df2.head(2))
# 方法3:
df3 = df[sorted(df.columns)]
print(df3.head(2))
# 方法4:
df4 = df.sort_index(axis=1, ascending=False)
print(df4.head(2))

在这里插入图片描述

2.46、大DataFrame修改默认显示的行和列数

''' 46、大DataFrame修改默认显示的行和列数 '''
df = pd.read_csv('datasets/Cars93_miss.csv')
pd.set_option('display.max_columns', 10)    #输出10列
pd.set_option('display.max_rows', 10)       #输出10行
print(df)

在这里插入图片描述

2.47、DataFrame数据小数位数设置

''' 47、DataFrame数据小数位数设置 '''
df = pd.DataFrame(np.random.random(4), columns=['random'])
print(df)
#方法1: Rounding
df1 = df.round(4)
print(df1)
#方法2: Use apply to change format
df3 = df.apply(lambda x: '%.4f' % x, axis=1)
print(df3)
df4 = df.applymap(lambda x: '%.4f' % x)
print(df4)
#方法3: Use set_option
df5 = pd.set_option('display.float_format', lambda x: '%.4f' % x)
print(df5)
#方法4: Assign display.float_format
pd.options.display.float_format = '{:.4f}'.format
print(df)

在这里插入图片描述

2.48、 DataFrame数据小数转百分比显示

''' 48、 DataFrame数据小数转百分比显示 '''
df = pd.DataFrame(np.random.random(4), columns=['random'])
print(df)
df1 = df.applymap(lambda x: '%.2f%%' % (x*100))
# out = df.style.format({'random': '{0:.2%}'.format,})      # 这个不成功
print(df1)

在这里插入图片描述

2.49、DataFrame数据每隔20行读取

''' 49、DataFrame数据每隔20行读取 '''
df = pd.read_csv('datasets/Cars93_miss.csv')
print(df.iloc[::20, :][['Manufacturer', 'Model', 'Type']])

在这里插入图片描述

2.50、创建DataFrame主键

''' 50、创建DataFrame主键 '''
df = pd.read_csv('datasets/Cars93_miss.csv', usecols=[0,1,2,3,5])
df[['Manufacturer', 'Model', 'Type']] = df[['Manufacturer', 'Model', 'Type']].fillna('missing')     # object列空值用字符串填充
df.index = df.Manufacturer + '_' + df.Model + '_' + df.Type     # 三列合并为index
print(df)
print(df.index.is_unique)       # True  判断index是否唯一

在这里插入图片描述

2.51、获取DataFrame某一列中第n大的值索引

''' 51、获取DataFrame某一列中第n大的值索引 
Series.argsort(axis=0, kind='quicksort', order=None)  # 对series值进行排序的整数索引。
'''
df = pd.DataFrame(np.random.randint(1, 30, 21).reshape(-1,3), columns=list('abc'))
print(df['a'])
print(df['a'].sort_values())
print(df['a'].sort_values()[::-1])
print(df['a'].sort_values()[::-1][1:3].index)       # Int64Index([5, 0], dtype='int64')
print(df['a'].sort_values()[::-1][1:3].index[0])    # 5

在这里插入图片描述

2.52、获取DataFrame某一列中第n大的值大于指定值得索引

''' 52、获取DataFrame某一列中第n大的值大于指定值的索引 '''
ser = pd.Series(np.random.randint(1, 100, 15))
print('ser: ', ser.tolist(), 'mean: ', round(ser.mean()))
print(np.where(ser > round(ser.mean()))[0])

在这里插入图片描述

2.53、获取DataFrame中行和大于100的行

''' 53、获取DataFrame中行和大于100的行 '''
df = pd.DataFrame(np.random.randint(10, 40, 60).reshape(-1, 4))
# 求行和
rowsums = df.apply(np.sum, axis=1)  # axis=1指定行
print(rowsums)
print(df.iloc[np.where(rowsums > 110)])

在这里插入图片描述

2.54、 Series or DataFrame中使用分位数填充超限区域

''' 54、 Series or DataFrame中使用分位数填充超限区域 
np.logspace(start=指数开始值,stop=指数结束值,num=个数,base=对数的底(默认为10), endpoint=包含结束值(默认包含))    # 对数等比数列
'''
#需求:使用0.05分位数和0.95分位数分别替换小于和大于该分位数的区域
ser = pd.Series(np.logspace(-2, 2, 30))     # 10**(-2)=0.01   10**2=100  
print(ser.round(4).tolist())
def cap_outliers(ser, low_perc, high_perc):
    low, high = ser.quantile([low_perc, high_perc])     # 指定分位数
    print(low_perc, '%ile: ', low, '|', high_perc, '%ile: ', high)
    ser[ser < low] = low
    ser[ser > high] = high
    return(ser)
capped_ser = cap_outliers(ser, .05, .95)
print(capped_ser.tolist())

在这里插入图片描述

2.55、去除指定值将DataFrame转换为最大方阵

''' 55、去除指定值将DataFrame转换为最大方阵 '''
df = pd.DataFrame(np.random.randint(-20, 50, 100).reshape(10,-1))
print(df)
#去除负值
arr = df[df > 0].values.flatten()       # numpy.ndarray.flatten(),即返回一个一维数组。大于0的元素
arr_qualified = arr[~np.isnan(arr)]     # 去除nan值,依然是一维数组
#寻找最大可能的方阵维度
n = int(np.floor(arr_qualified.shape[0]**.5))   # np.floor()返回不大于输入参数的最大整数,为浮点型
#方阵转换
top_indexes = np.argsort(arr_qualified)[::-1]
output = np.take(arr_qualified, sorted(top_indexes[:n**2])).reshape(n, -1)  # np.take(arr, indices)沿轴取数组中的元素,indices第几个。
print(output)

在这里插入图片描述

2.56、DataFrame两行交换

''' 56、DataFrame两行交换 '''
df = pd.DataFrame(np.arange(25).reshape(5, -1))
print(df)
def swap_rows(df, i1, i2):
    a, b = df.iloc[i1, :].copy(), df.iloc[i2, :].copy()
    df.iloc[i1, :], df.iloc[i2, :] = b, a
    return df
print(swap_rows(df, 1, 2))

在这里插入图片描述

2.57、DataFrame逆序输出

''' 57、DataFrame逆序输出 '''
df = pd.DataFrame(np.arange(25).reshape(5, -1))
print(df)
#方法 1
df.iloc[::-1, :]
#方法 2
print(df.loc[df.index[::-1], :])

在这里插入图片描述

2.58、DataFrame转对角矩阵

''' 58、DataFrame转对角矩阵 
pd.get_dummies()特征提取,one-hot encoding的基本思想:将离散型特征的每一种取值都看成一种状态,若你的这一特征中有N个不相同的取值,
                那么我们就可以将该特征抽象成N种不同的状态,one-hot编码保证了每一个取值只会使得一种状态处于“激活态”,
                也就是说这N种状态中只有一个状态位值为1,其他状态位都是0。
'''
df = pd.DataFrame(np.arange(25).reshape(5,-1), columns=list('abcde'))
print(df)
df_onehot = pd.concat([pd.get_dummies(df['a']), df[list('bcde')]], axis=1)
print(df_onehot)

在这里插入图片描述

2.59、DataFrame那一列含有最多行最大值

''' 59、DataFrame那一列含有最大值最多的行 '''
df = pd.DataFrame(np.random.randint(1,100, 40).reshape(10, -1))
print(df)
print(df.apply(np.argmax, axis=1))
print(df.apply(np.argmax, axis=1).value_counts())
print(df.apply(np.argmax, axis=1).value_counts().index)
print('最大值最多的行: ', df.apply(np.argmax, axis=1).value_counts().index[0])

在这里插入图片描述

2.60、DataFrame创建新列:每行为行号(按欧几里得距离而来)

''' 60、DataFrame创建新列:每行为行号(按欧几里得距离而来) '''
df = pd.DataFrame(np.random.randint(1,100, 40).reshape(5, -1), columns=list('abcdefgh'), index=list('mnprs'))
print(df)
# init outputs
nearest_rows = []
nearest_distance = []
# iterate rows.
for i, row in df.iterrows():  # iterrows() 是在数据框中的行进行迭代的一个生成器,它返回每行的索引及一个包含行本身的对象。
    curr = row
    rest = df.drop(i)
    e_dists = {}  # init dict to store euclidean dists for current row.
    # iterate rest of rows for current row
    for j, contestant in rest.iterrows():
        # compute euclidean dist and update e_dists
        e_dists.update({j: round(np.linalg.norm(curr.values - contestant.values))})
    # update nearest row to current row and the distance value
    nearest_rows.append(max(e_dists, key=e_dists.get))
    nearest_distance.append(max(e_dists.values()))
df['nearest_row'] = nearest_rows
df['dist'] = nearest_distance
print(df)

在这里插入图片描述

2.61、求DataFrame各列之间最大相关系数

''' 61、求DataFrame各列之间「最大」相关系数 '''
df = pd.DataFrame(np.random.randint(1,100, 80).reshape(8, -1), columns=list('pqrstuvwxy'), index=list('abcdefgh'))
print(df)
abs_corrmat = np.abs(df.corr())     # df.corr获取两列之间的相关性
print(abs_corrmat)
max_corr = abs_corrmat.apply(lambda x: sorted(x)[-2])
print('Maximum Correlation possible for each column: \n', np.round(max_corr.tolist(), 4))

在这里插入图片描述

2.62、DataFrame创建一列:包含每行中最小值与最大值比值

''' 62、DataFrame创建一列:包含每行中最小值与最大值比值 '''
df = pd.DataFrame(np.random.randint(1,100, 80).reshape(8, -1))
print(df)
#方法 1
min_by_max = df.apply(lambda x: np.min(x)/np.max(x), axis=1)
print(min_by_max)
#方法 2
min_by_max = np.min(df, axis=1)/np.max(df, axis=1)
print(min_by_max)

在这里插入图片描述

2.63、DataFrame创建一列:包含每行中第二大的值

''' 2.63、DataFrame创建一列:包含每行中第二大的值 '''
df = pd.DataFrame(np.random.randint(1,100, 80).reshape(8, -1))
print(df)
out = df.apply(lambda x: x.sort_values().unique()[-2], axis=1)
df['penultimate'] = out
print(df)

在这里插入图片描述

2.64、DataFrame每列按特定方式归一化

''' 64、DataFrame每列按特定方式归一化 '''
df = pd.DataFrame(np.random.randint(1,100, 80).reshape(8, -1))
print(df)
# 均值、标准差归一化
out1 = df.apply(lambda x: ((x - x.mean())/x.std()).round(2))
print('均值、标准差归一化:\n',out1)
# 最大最小值归一化
out2 = df.apply(lambda x: ((x.max() - x)/(x.max() - x.min())).round(2))
print('最大最小值归一化:\n', out2)  

在这里插入图片描述

2.65、计算DataFrame每行与后一行的相关系数

''' 65、计算DataFrame每行与后一行的相关系数 '''
df = pd.DataFrame(np.random.randint(1,100, 80).reshape(8, -1))
print(df)
print([df.iloc[i].corr(df.iloc[i+1]).round(2) for i in range(df.shape[0])[:-1]])

在这里插入图片描述

2.66、DataFrame对角线元素替换为0

''' 66、DataFrame对角线元素替换为0 '''
df = pd.DataFrame(np.random.randint(1,100, 100).reshape(10, -1))
print(df)
for i in range(df.shape[0]):
    df.iat[i, i] = 0
    df.iat[df.shape[0]-i-1, i] = 0
print(df)

在这里插入图片描述

2.67、DataFrame按某列分组、提取某个分组

''' 67、DataFrame按某列分组、提取某个分组 '''
df = pd.DataFrame({'col1': ['apple', 'banana', 'orange'] * 3,
                   'col2': np.random.rand(9),
                   'col3': np.random.randint(0, 15, 9)})
print(df)
df_grouped = df.groupby(['col1'])#按col1列分组
#获取指定分组,此处取apple组
# 方法 1
df1= df_grouped.get_group('apple')   # get_group()函数返回一个按照分组得到的DF对象。
print(df1)
# 方法 2
for i, dff in df_grouped:
    if i == 'apple':
        print(dff)

在这里插入图片描述

2.68、DataFrame按另外列分组、提取当前列中指定值(看下方例子,需求不好描述)

''' 68、DataFrame按另外列分组、提取当前列中指定值(看下方例子,需求不好描述) '''
df = pd.DataFrame({'fruit': ['apple', 'banana', 'orange'] * 3,
                   'taste': np.random.rand(9),
                   'price': np.random.randint(0, 15, 9)})
print(df)
df_grpd = df['taste'].groupby(df.fruit)     # taste值按fruit类别排序
print(df_grpd.get_group('banana'))                  # 获取fruit中的banana组
print(df_grpd.get_group('banana').sort_values())    # 对fruit中的banana组的值排序
print(df_grpd.get_group('banana').sort_values().iloc[-2])   # 对fruit中的banana组的值排序,取第二大值

在这里插入图片描述

2.69、DataFrame分组(看下方例子,需求不好描述)

''' 69、DataFrame分组(看下方例子,需求不好描述) '''
df = pd.DataFrame({'fruit': ['apple', 'banana', 'orange'] * 3,
                   'rating': np.random.rand(9),
                   'price': np.random.randint(0, 15, 9)})
print(df)
print(df.groupby('fruit', as_index=False))          #按fruit分组,as_index='False'指定'fruit'不做index
print(df.groupby('fruit', as_index=False)['price']) #按fruit分组、求每类fruit的均价
print(df.groupby('fruit', as_index=False)['price'].mean())#按fruit分组、求每类fruit的均价

在这里插入图片描述

2.70、两个DataFrame使用类似SQL 中INNER JOIN拼接

''' 70、两个DataFrame使用类似SQL 中INNER JOIN拼接 '''
# Join dataframes df1 and df2 by ‘fruit-pazham’ and ‘weight-kilo’.
df1 = pd.DataFrame({
    'fruit': ['apple', 'banana', 'orange'] * 3,
    'weight': ['high', 'medium', 'low'] * 3,
    'price': np.random.randint(0, 15, 9)
})
df2 = pd.DataFrame({
    'pazham': ['apple', 'orange', 'pine'] * 2,
    'kilo': ['high', 'low'] * 3,
    'price': np.random.randint(0, 15, 6)
})
# Solution
df3 = pd.merge(df1, df2, how='inner', left_on=['fruit', 'weight'], right_on=['pazham', 'kilo'], suffixes=['_left', '_right'])
print(df3)

在这里插入图片描述

2.71、移除DataFrame1中在DataFrame2出现的行

''' 71、移除DataFrame1中在DataFrame2出现的行 
Series.all(axis=0, bool_only=None, skipna=True, level=None, **kwargs)   # 函数返回是否所有元素都为True(可能在某个轴上)'''
df1 = pd.DataFrame({
    'fruit': ['apple', 'orange', 'banana'] * 3,
    'weight': ['high', 'medium', 'low'] * 3,
    'price': np.arange(9)   })
print(df1)
df2 = pd.DataFrame({
    'fruit': ['apple', 'orange', 'pine'] * 2,
    'weight': ['high', 'medium'] * 3,
    'price': np.arange(6)   })
print(df2)
print(df1[~df1.isin(df2).all(axis=1)])   # 1轴上

在这里插入图片描述

2.72、取出DataFrame中两列值相等的行号

''' 72、取出DataFrame中两列值相等的行号 '''
df = pd.DataFrame({
    'fruit1': np.random.choice(['apple', 'orange', 'banana'], 10),
    'fruit2': np.random.choice(['apple', 'orange', 'banana'], 10)
})
print(df)
print(np.where(df.fruit1 == df.fruit2))

在这里插入图片描述

2.73、DataFrame中新建两列:滞后列和提前列(看下方例子,需求BT)

''' 73、DataFrame中新建两列:滞后列和提前列(看下方例子,需求BT) '''
df = pd.DataFrame(np.random.randint(1, 100, 20).reshape(-1, 4), columns=list('abcd'))
print(df)
df['a_lag1'] = df['a'].shift(1)         # a列每行值向后移一位
df['b_lead1'] = df['b'].shift(-1)       # b列每行值向前移一位
print(df)

在这里插入图片描述

2.74、DataFrame中所有值出现频次统计

''' 74、DataFrame中所有值出现频次统计 
numpy中的ravel()、flatten()、squeeze()都有将多维数组转换为一维数组的功能,区别:
ravel():如果没有必要,不会产生源数据的副本
flatten():返回源数据的副本,平时使用的时候flatten()更为合适
squeeze():只能对维数为1的维度降维
另外,reshape(-1)也可以“拉平”多维数组
'''
df = pd.DataFrame(np.random.randint(1, 10, 20).reshape(-1, 4), columns=list('abcd'))
print(df)
print(df.values.ravel())
print(pd.value_counts(df.values.ravel()))

在这里插入图片描述

2.75、拆分DataFrame中某列文本为两列

''' 75、拆分DataFrame中某列文本为两列 '''
df = pd.DataFrame(["STD, City   State", "33, Kolkata    West Bengal", "44, Chennai  Tamil Nadu", "40, Hyderabad Telengana",
    "80, Bangalore    Karnataka"], columns=['row'])
print(df)
print(df.columns)
df_out = df.row.str.split(',|\t', expand=True)  # 拆分
new_header = df_out.iloc[0]                     # 第一列设置为标题
df_out = df_out[1:]
df_out.columns = new_header
print(df_out)
print(df_out.columns)

在这里插入图片描述

2.100 代码块

import pandas as pd
import numpy as np

''' 1、pandas导入、查看版本'''
import pandas as pd
#pandas输出版本信息
print(pd.__version__)
#pandas输出详细版本信息、 Python版本、相关程序包、操作系统等信息以json格式输出
print(pd.show_versions(as_json=True))
#pandas输出相关信息以默认格式输出
print(pd.show_versions())


''' 2、使用python list、python dict、numpy.ndarray创建pandas.Series '''
mylist = list('abcedfghijklmnopqrstuvwxyz')     # python list
myarr = np.arange(26)                           #numpy.ndarray
mydict = dict(zip(mylist, myarr))               #python dict
ser1 = pd.Series(mylist)
ser2 = pd.Series(myarr)
ser3 = pd.Series(mydict)
print(ser1.head(3))
print(ser2.head(3))
print(ser3.head(3))


''' 3、将pandas.Series转化为pandas.DataFrame '''
mylist = list('abcedfghijklmnopqrstuvwxyz')
myarr = np.arange(26)
mydict = dict(zip(mylist, myarr))
ser = pd.Series(mydict)
#to_frame()结合reset_index()使用
df = ser.to_frame().reset_index()
print(type(df))
print(df.head())


''' 4、将多个pandas.Series合并为一个pandas.DataFrame '''
ser1 = pd.Series(list('abcedfghijklmnopqrstuvwxyz'))
ser2 = pd.Series(np.arange(26))
# 解决方法1
df = pd.concat([ser1, ser2], axis=1)
print('1-------------')
print(df.head())
# 解决方法2
df = pd.DataFrame({'col1': ser1, 'col2': ser2})
print('2-------------')
print(df.head())


''' 5、修改pandas.Series index名称 '''
ser = pd.Series(list('abcedfghijklmnopqrstuvwxyz'))
print(ser.head(3))
print(f'原始Sersies index名称:{ser.name}')
ser.name = 'alphabets'
print(ser.head(3))
print(f'修改后Sersies index名称:{ser.name}')


''' 6、 pandas.Series1中移除pandas.Series1中和pandas.Series2共同的部分--差集 '''
ser1 = pd.Series([1, 2, 3, 4, 5])
ser2 = pd.Series([4, 5, 6, 7, 8])
ser3 = ser1[~ser1.isin(ser2)]
print(ser3)


''' 7、求pandas.Series1和pandas.Series2的交集、并集、差集 '''
ser1 = pd.Series([1, 2, 3, 4, 5])
ser2 = pd.Series([4, 5, 6, 7, 8])
ser_i = pd.Series(np.intersect1d(ser1, ser2))   # intersect 交集
ser_u = pd.Series(np.union1d(ser1, ser2))       # union 并集
ser_s = ser_u[~ser_u.isin(ser_i)]               # Subtraction 差集
print("交集-------")
print(ser_i)
print("并集-------")
print(ser_u)
print("差集-------")
print(ser_s)


''' 8、求pandas.Series分位数(最小值、1/4分位数、中位数、3/4分位数、最大值) '''
state = np.random.RandomState(100)
ser = pd.Series(state.normal(10, 5, 25))
print(ser)
print(np.percentile(ser, q=[0, 25, 50, 75, 100]))#可是设置其它任何想输出的分位数


''' 9、求pandas.Series()频数 '''
# numpy.take(arr,indices,axis = None,out = None,mode ='raise') # 沿轴取数组中的元素。
# pd.Series([list],index=[list]) 参数为list ,index为可选参数,若不填写则默认为index从0开始
arr = list('abcdefgh')                  # 源数组
indices = np.random.randint(8, size=30) # 取索引值为0-7随机整数的30个元素,组成一个源数组索引值的数组
ser = pd.Series(np.take(arr, indices))  # 从8个元素的源数组中按索引值数组(列表)随机取30个元素,组成Series
print(ser)
print(ser.value_counts())   # 求频数


''' 10、输出pandas.Series()中频数排第一二位的、其它的替换为other '''
ser = pd.Series(np.random.randint(1, 6, 12)) # 生成12个1-5的随机数,转换为Series
print(ser)
print(ser.value_counts())   # 输出统计结果
ser[~ser.isin(ser.value_counts().index[:2])] = 'Other' 
print(ser)


''' 11、将pandas.Series()均分为10个区间、每个值使用区间名称标记 '''
np.random.seed(666)  # 用固定的种子锁定随机结果,让结果可复现
ser = pd.Series(np.random.random(20))
print(ser)
ser_qcut = pd.qcut(ser,
        q=[0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1],
        labels=['1st', '2nd', '3rd', '4th', '5th', '6th', '7th', '8th', '9th','10th']
        )
print(ser_qcut)


''' 12、将pandas.Series()转换为指定shape的pandas.DataFrame '''
nums = np.random.randint(1, 10, 35)
ser = pd.Series(nums)
print(ser.values)
print(type(ser.values))
df1 = pd.DataFrame(ser.values.reshape(7,5))
df2 = pd.DataFrame(nums.reshape(7, 5))
print(df1)
print('--------------')
print(df2)


''' 13、取出pandas.Series()中满足条件数据的位置index '''
np.random.seed(666) 
ser = pd.Series(np.random.randint(1, 10, 15))
print(ser)
arr_i = np.argwhere(ser.values % 3 == 0)
print(type(arr_i)) # 数据为3的倍数的位置index
print(arr_i) # 数据为3的倍数的位置index
print([i for i in arr_i])
print([i[0] for i in arr_i])


''' 14、取出pandas.Series()指定位置的数据 '''
ser = pd.Series(list('abcdefghijklmnopqrstuvwxyz'))
print(ser)
pos = [0, 4, 8, 14, 20]#待取出位置
print(ser.take(pos))


''' 15、pandas.Series()水平、垂直合并 '''
ser1 = pd.Series(range(5))
ser2 = pd.Series(list('abcde'))
# 垂直合并
ser3 = ser1.append(ser2)
print(ser3)
ser4 = pd.concat([ser1, ser2], axis=0)
print(ser4)
# 水平合并
df = pd.concat([ser1, ser2], axis=1)
print(df)


''' 16、输出pandas.Series()子集的index号 '''
# 获取ser2在ser1中的index号
ser1 = pd.Series([10, 9, 6, 5, 3, 1, 12, 8, 13])
ser2 = pd.Series([1, 3, 10, 13])
# ser2 = pd.Series([1, 3, 10, 13, 18])
# 方法1
# 三个参数np.where(condition, x, y):满足条件(condition),输出x,不满足输出y。
# 一个参数np.where(condition):则输出满足条件 (即非0) 元素的坐标,坐标以tuple的形式给出
# condition条件可以使用广播
print(np.where(ser1 == ser2[0]))  # 结果为元组 (array([5], dtype=int64),)
print(np.where(ser1 == ser2[0])[0])  # 结果为数组 [5]
print([np.where(ser1 == i)[0] for i in ser2]) # [array([5], dtype=int64), array([4], dtype=int64), array([0], dtype=int64), array([8], dtype=int64)]
print([np.where(ser1 == i)[0][0] for i in ser2]) # [5, 4, 0, 8]
# 配合ser2 = pd.Series([1, 3, 10, 13, 18]),当指定值找不到用if的三元表达式
# print([np.where(ser1 == i)[0][0] if len(np.where(ser1 == i)[0])>0 else np.where(ser1 == i)[0] for i in ser2]) # [5, 4, 0, 8]
# 方法2
print([np.where(ser1 == i)[0].tolist()[0] for i in ser2]) # [5, 4, 0, 8]
# 方法3
# Pandas Index.get_loc()函数返回所指定值的索引位置,切片或布尔掩码。
print([pd.Index(ser1).get_loc(i) for i in ser2]) # [5, 4, 0, 8]


''' 17、求真实和预测pd.Series之间的均方误差损失函数(MSE,mean squared error) '''
truth = pd.Series(range(10))
pred = pd.Series(range(10)) + np.random.random(10)
print(np.mean((truth-pred)**2))


''' 18、pd.Series字符串型数据首字母大写转换 '''
ser = pd.Series(['how', 'to', 'kick', 'ass?'])
# 方法一title()结合title()
print(ser.map(lambda x: x.title()))
# 方法二upper()结合lambda
print(ser.map(lambda x: x[0].upper() + x[1:]))
# 方法三title()结合列表推导式
print(pd.Series([i.title() for i in ser]))
'''Series中的map()函数可以接受一个函数或含有映射关系的字典型对象,使用map()是一种实现元素级转换以及其他数据清理工作的便捷方式。(DataFrame中的对应的是applymap()函数以及apply()---对每一行操作,等同于axis=0)'''
data = pd.DataFrame({'food':['bacon','pulled pork','bacon','Pastrami','corned beef','Bacon','pastrami','honey ham','nova lox'],
                  'ounces':[4,3,12,6,7.5,8,3,5,6]})
print(data)
meat_to_animal = {
    'bacon':'pig',
    'pulled pork':'pig',
    'pastrami':'cow',
    'corned beef':'cow',
    'honey ham':'pig',
    'nova lox':'salmon'    }  
data['animal'] = data['food'].map(str.lower).map(meat_to_animal) 
print(data) 


''' 19、pd.Series字符串型数据字符长度计算 '''
ser1 = pd.Series(['how', 'to', 'kick', 'ass?'])
print(ser1)
ser2 = ser1.map(lambda x: len(x))
print(ser2)
print(type(ser2))


''' 20、pd.Series中两两数之间差异 '''
ser = pd.Series([1, 3, 6, 10, 15, 11, 27, 35])
print(ser.diff().tolist())


''' 21、pd.Series中日期字符串转换为datetime格式 '''
ser = pd.Series(['01 Jan 2010', '02-02-2011', '20120303', '2013/04/04', '2014-05-05', '2015-06-06T12:20'])
print(ser)
# 方法一
from dateutil.parser import parse  # 与日期相关库里的一个日期解析器,能够将字符串转换为日期格式
print(ser.map(lambda x: parse(x)))
# 方法二
print(pd.to_datetime(ser))


''' 22、获取pd.Series日期字符串中时间对象 '''
ser = pd.Series(['01 Jan 2011', '02-02-2011', '20120303', '2013/04/04', '2014-05-05', '2015-06-06T12:20'])
print(ser)
from dateutil.parser import parse
ser_ts = ser.map(lambda x: parse(x))    # 转为pd标准日期时间格式
print(ser_ts)
# 处于该月中的第几天
print("Date: ", ser_ts.dt.day.tolist())
# 处于该年的第几天
print("Day number of year: ", ser_ts.dt.dayofyear.tolist())
# 处于该年的第几周
print("Week number: ", ser_ts.dt.isocalendar().week)
# isocalendar数据框
print("df_isocalendar: ", ser_ts.dt.isocalendar())
# 周几
print("Day of week: ", ser_ts.dt.day_name().tolist())


''' 23、pd.Series日期字符串中修改为按指定日期输出 '''
ser = pd.Series(['Jan 2010', 'Feb 2011', 'Mar 2012'])
# 方法1
print(pd.to_datetime(ser))          # 给定年月,日默认1
from dateutil.parser import parse
# Parse the date
ser_ts = ser.map(lambda x: parse(x))# 给定年月,日默认为当前系统日期中的日
print(ser_ts)
# Construct date string with date as 4
ser_datestr = ser_ts.dt.year.astype('str') + '-' + ser_ts.dt.month.astype('str') + '-' + '04'
print(ser_datestr)
# Format it.
print('~~~~~~~~~~~~~', [parse(i).strftime('%Y-%m-%d') for i in ser_datestr])
# 方法2
print(ser.map(lambda x: parse('04' + x)))   # 日 + 给定年月
print(ser.map(lambda x: parse(x + '55')))   # 给定年月,日默认为当前系统日期中的日,加数为秒


''' 24、输出pd.Series中至少包含两个元音字符的数据 '''
ser = pd.Series(['Apple', 'Orange', 'Plan', 'Python', 'Money'])
from collections import Counter
print(ser.map(lambda x: [Counter(x.lower()).get(i, 0) for i in list('aeiou')]))
mask = ser.map(lambda x: sum([Counter(x.lower()).get(i, 0) for i in list('aeiou')]) >= 2)
print('apple中每个字母的次数:', Counter('Apple'.lower()))      # Counter({'p': 2, 'a': 1, 'l': 1, 'e': 1})
print('计数器类型:', type(Counter('Apple'.lower())))          # <class 'collections.Counter'> 类似字典
print('查找计数器中字母a的个数:', Counter('Apple'.lower()).get('a', 0))     # 找不到,默认返回0
print('查找计数器中字母i的个数:', Counter('Apple'.lower()).get('i', 0))     # 找不到,默认返回0
print(mask)         
print(ser[mask])


''' 25、输出pd.Series中有效的email地址 '''
# 三种方法
emails = pd.Series(['buying books at amazom.com', 'rameses@egypt.com', 'matt@t.co', 'narendra@modi.com'])
# Solution 1 (as series of strings)
import re
pattern ='[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}'
mask = emails.map(lambda x: bool(re.match(pattern, x)))
print(emails[mask])
# Solution 2 (as series of list)
print(emails.str.findall(pattern, flags=re.IGNORECASE))
# Solution 3 (as list)
print([x[0] for x in [re.findall(pattern, email) for email in emails] if len(x) > 0])


''' 26、pd.Series1按pd.Series2分组并求均值 
numpy.linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)  主要用来创建等差数列。
start:返回样本数据开始点,stop:返回样本数据结束点,num:生成的样本数据量,默认为50,endpoint:True则包含stop;False则不包含stop
retstep:如果为True则结果会给出数据间隔,dtype:输出数组类型,axis:0(默认)或-1
'''
fruit = pd.Series(np.random.choice(['apple', 'banana', 'carrot'], 10))  # 从已有列表随机选择10个元素组成Series
weights = pd.Series(np.linspace(1, 10, 10))     # 创建1-10的浮点数series
weights1 = pd.Series(list(range(1,11)))         # 创建1-10的整数series
print(weights.groupby(fruit).mean())        # 重量按水果种类分组并求各组水果重量的平均值


''' 27、计算两个pd.Series之间的欧式距离 : 矩阵元素平方和,再开根号
np.linalg.norm(x, ord=None, axis=None, keepdims=False)  # 求范数
①x: 表示矩阵(也可以是一维);②ord:范数类型,ord=None:默认情况下,是求整体的矩阵元素平方和,再开根号。
ord=2-2范数,求特征值,然后求最大特征值得算术平方根;ord=1-1范数,求列和的最大值;ord=np.inf无穷范数,求行和的最大值;
'''
p = pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
q = pd.Series([10, 9, 8, 7, 6, 5, 4, 3, 2, 1])
# 方法1 
print('欧式距离:', sum((p - q)**2)**.5)
# 方法2
print("默认参数(矩阵整体元素平方和开根号,不保留矩阵二维特性):", np.linalg.norm(p-q))


''' 28、求pd.Series局部峰值index 
numpy.diff(a, n=1,axis=-1),沿着指定轴计算第N维的离散差值,后一个元素减去前一个元素,a:输入矩阵,n:可选,代表要执行几次差值,axis:默认是最后一个
np.sign(x),取数字x的符号(数字前的正负号),x>0返回1,x<0返回-1,x=0返回0
'''
ser = pd.Series([2, 10, 3, 4, 9, 10, 2, 7, 3])
print(np.diff(ser))                     # [ 8 -7  1  5  1 -8  5 -4]  后-前
print(np.sign(np.diff(ser)))            # [ 1 -1  1  1  1 -1  1 -1]  只保留符号
dd = np.diff(np.sign(np.diff(ser)))     #                            找到前后差值正负变换点,也就是曲线的拐点
print(dd)                               # [-2  2  0  0 -2  2 -2]
peak_locs = np.where(dd == -2)[0] + 1
print(peak_locs)                        # [1 5 7]


''' 29、pd.Series字符串数据中使用最低频字符填充空格 '''
ser = pd.Series(list('dbc deb abed gade'))
freq = ser.value_counts()
print(freq)
print(freq.index)
least_freq = freq.index[-1]
str = "".join(ser.replace(' ', least_freq))
print(str)


''' 30、创建时间序列数据,赋予随机值 
pandas.date_range(start=None, end=None, periods=None, freq='D', tz=None, normalize=False, name=None, closed=None, **kwargs)
该函数主要用于生成一个固定频率的时间索引,在调用构造方法时,必须指定start、end、periods中的两个参数值,否则报错。
主要参数说明:
periods:固定时期,取值为整数或None
freq:日期偏移量,取值为string或DateOffset,默认为'D',
    默认freq = 'D':每日历日,B:每工作日,H:每小时,T/MIN:每分,S:每秒,L:每毫秒(千分之一秒),U:每微秒(百万分之一秒)
    freq = 'W-MON':每周从指定星期几开始算起,这里是周一。星期几缩写:MON/TUE/WED/THU/FRI/SAT/SUN
    freq = 'WOM-2MON':每月的第几个星期几开始算,这里是每月第二个星期一
    freq = 'M':M:每月最后一个日历日;Q-月:指定月为季度末,每个季度末最后一月的最后一个日历日;A-月:每年指定月份的最后一个日历日
            月缩写:JAN/FEB/MAR/APR/MAY/JUN/JUL/AUG/SEP/OCT/NOV/DEC;所以Q-月只有三种情况:1-4-7-10,2-5-8-11,3-6-9-12
    freq = 'BM':BM:每月最后一个工作日;BQ-月:指定月为季度末,每个季度末最后一月的最后一个工作日;BA-月:每年指定月份的最后一个工作日
    freq = 'MS':M:每月第一个日历日;Q-月:指定月为季度末,每个季度末最后一月的第一个日历日;A-月:每年指定月份的第一个日历日
    freq = 'BMS':BM:每月第一个工作日;BQ-月:指定月为季度末,每个季度末最后一月的第一个工作日;BA-月:每年指定月份的第一个工作日
    freq = '7D':7天
    freq = '2h30min':2小时30分钟
    freq = '2M':2月,每月最后一个日历日
normalize:若参数为True表示将start、end参数值正则化到午夜时间戳
name:生成时间索引对象的名称,取值为string或None
closed:可以理解成在closed=None情况下返回的结果中,若closed=‘left’表示在返回的结果基础上,再取左开右闭的结果,
        若closed='right'表示在返回的结果基础上,再取做闭右开的结果
'''
ser = pd.Series(np.random.randint(1,10,10), pd.date_range('2000-01-01', periods=10, freq='W-SAT'))
print(ser)


''' 31、缺省的时间序列值 不同方式填充 
resample()是一个对常规时间序列数据重新采样和频率转换的便捷的方法,可以对原样本重新处理,
resample(rule,how=None,axis=0,fill_method=None,closed=None,label=None,convention=“start”,kind=None,loffset=None,limit=None,base=0,on=None,level=None)
    rule:表示重采样频率的字符串或DateOffset,比如D(天)、M(月)、5min(5分钟)、5D(5天)、2M(2个月)、60T(60分钟)等。
    how:用于产生聚合值的函数名或函数数组,默认为None。
    fill_method:表示升采样时如何插值,可以取值为fill、bfill或None,默认为None。
    closed:设置降采样哪一端是闭合的,可以取值为right或left。若设为right,则表示划分为左开右闭的区间;若设为left,则表示划分为左闭右开的区间。
    label:表示降采样时设置聚合值的标签。
    convention:重采样日期时,低频转高频采用的约定,可以取值为start或end,默认为start。
    limit:表示前向或后向填充时,允许填充的最大时期数。
    ser.resample('60T', base=30):base=30时,60分钟的时间间隔将移动30分钟
'''
ser = pd.Series([1,10,3, np.nan], index=pd.to_datetime(['2000-01-01', '2000-01-03', '2000-01-06', '2000-01-08']))
print(ser)
f_ser = ser.resample('D').ffill()  # 前填充
print(f_ser)
b_ser = ser.resample('D').bfill()  # 后填充
print(b_ser)
bf_ser = ser.resample('D').bfill().ffill()  # 先后填充,如后无值则前填充
print(bf_ser)


''' 32、找出pd.Series中自相关性最大的数据 
numpy.random.normal(loc=0,scale=1e-2,size=shape)  随机生成一个正态分布
    loc(float):正态分布的均值,对应着这个分布的中心。loc=0说明这一个以Y轴为对称轴的正态分布,
    scale(float):正态分布的标准差,对应分布的宽度,scale越大,正态分布的曲线越矮胖,scale越小,曲线越高瘦。
    size(int 或者整数元组):输出的值赋在shape里,默认为None。
Series.autocorr(lag=1)函数计算lag-N自相关,lag:执行自相关之前要应用的滞后次数。
np.abs(x)、np.fabs(x):计算数组各元素的绝对值
np.argmax(array, axis):用于返回一个numpy数组中最大值的索引值。
'''
ser = pd.Series(np.arange(20) + np.random.normal(1, 10, 20))
print(np.random.normal(1, 10, 20))
print(np.arange(20) + np.random.normal(1, 10, 20))
autocorrelations = [ser.autocorr(lag = i).round(2) for i in range(18)]
print(autocorrelations)
print('\n Lag 自相关性最大的位置: ', np.argmax(np.abs(autocorrelations[1:]))+1, '\n')


''' 33、从一个csv 文件中每间隔50行取数据生成pandas.DataFrame '''
# 方法1: 利用chunks分块和循环,这种方式可能造成数据列的排列顺序与原始数据不一致
df = pd.read_csv('datasets/BostonHousing.csv', chunksize=50)     # 分块读取csv超大文件,每块50行,生成分块df,此时并没有真正读取csv,只是定义了一个框架
df2 = pd.DataFrame()                        # 创建一个空的df2
for chunk in df:                            # 循环读取CSV,在同一个df中,每50行数据作为一组,不断覆盖写入,直至csv末尾
    df2 = df2.append(chunk.iloc[0,:])       # 把每个分块df的首行所有列追加到df2
print(df2.head(2))
# 方法2: 利用chunks分块和列表推导式
df = pd.read_csv('datasets/BostonHousing.csv', chunksize=50)
df3 = pd.concat([chunk.iloc[0] for chunk in df], axis=1)    # 纵向concat,每个series拼合到df2的最右侧
df3 = df3.transpose()   # 行列转置
print(df3.head(2))
# 方法3: Use csv reader
import csv          
with open('datasets/BostonHousing.csv', 'r') as f:
    reader = csv.reader(f)
    out = []
    for i, row in enumerate(reader):
        if i%50 == 0:                       # i只用于判断有没有读到数据
            out.append(row)
df4 = pd.DataFrame(out[1:], columns=out[0])
print(df4.head(2))


''' 34、从一个csv 文件取数据生成pandas.DataFrame(新增加一分类列) '''
##两种方式
# Solution 1: Using converter parameter
df = pd.read_csv('datasets/BostonHousing.csv', 
                 converters={'medv': lambda x: 'High' if float(x) > 25 else 'Low'}) # medv列大于25改为High,否则改为Low
print(df.head())
# Solution 2: Using csv reader
import csv
with open('datasets/BostonHousing.csv', 'r') as f:
    reader = csv.reader(f)
    out = []
    for i, row in enumerate(reader):
        if i > 0:
            row[13] = 'High' if float(row[13]) > 25 else 'Low'  # row[13]即为medv列
        out.append(row)
print(out[:3])          # out为二维数组,out[0]为表头,out[1:]为数据
df = pd.DataFrame(out[1:], columns=out[0])  # 利用二维数组第二行及以后的数据生成df,指定二维数组的第一行为列名
print(df.head())


''' 35、生成一个按规定步长平移的pandas.DataFrame '''
L = pd.Series(range(15))
def gen_strides(a, stride_len=5, window_len=5):
    n_strides = ((a.size-window_len)//stride_len) + 1
    return np.array([a[s:(s+window_len)] for s in np.arange(0, a.size, stride_len)[:n_strides]])
result = gen_strides(L, stride_len=2, window_len=4)
print(result)


''' 36、从一个csv 文件读取指定列生成pandas.DataFrame '''
#usecols参数设置
df = pd.read_csv('datasets/BostonHousing.csv', usecols=['crim', 'medv'])
print(df.head())


''' 37、输出DataFrame的行数、列数、数据类型、类型频数、Series转list '''
df = pd.read_csv('datasets/Cars93_miss.csv')
#  DataFrame的行数和列数
print(df.shape)                         # (93, 27)
# DataFrame各列数据类型
print(df.dtypes.head())
# 每种数据类型的频数
print(df.dtypes.value_counts())         # float64    18 , object      9
# DataFrame基础统计
print(df.describe())
# pd.Series转list 
print(df['Model'].tolist()[:5])    # ['Integra', 'Legend', '90', '100', '535i', ]


''' 38、输出满足某个规则的DataFrame数据行和列号 
np.where(condition):只有条件 (condition),没有x和y,则输出满足条件 (即非0) 元素的坐标.
    坐标以tuple的形式给出,原数组有多少维,输出的tuple中就包含几个数组,分别对应符合条件元素的各维坐标。
'''
df = pd.read_csv('datasets/Cars93_miss.csv')
print(df)
#输出Price值最大时的行和列号
print(df.values == np.max(df.Price))
result = np.where(df.values == np.max(df.Price)) #df.values输出DataFrame的值,为numpy.ndarray类型
print(result)
row, col = np.where(df.values == np.max(df.Price)) #df.values输出DataFrame的值,为numpy.ndarray类型
print(f'\n 行号:{row},列号:{col} \n')
print((df.values == np.max(df.Price))[row[0]][col[0]])


''' 39、修改DataFrame的列名称 '''
#修改某一列的名称
df = pd.read_csv('datasets/Cars93_miss.csv')
print(df.columns)
df1=df.rename(columns = {'Type':'CarType'})
print(df1.columns)
# 或者
#df.columns.values[2] = "CarType"   # 限定了位置,如果df结构改变就乱套了,不要用

# map函数修改某一匹配的名称:此处将名称中的.替换为下划线
df.columns = df.columns.map(lambda x: x.replace('.', '_'))
print(df.columns)


''' 40、DataFrame中是否有缺失值确认 
DataFrame.any()与all():any()一个序列中满足一个True,则返回True;all()一个序列中所有值为True时,返回True
'''
df = pd.read_csv('datasets/Cars93_miss.csv')
print(df)
print(df.isnull())
print(df.isnull().values)
print(df.isnull().values.any())


''' 41、DataFrame中缺省值统计 '''
df = pd.read_csv('datasets/Cars93_miss.csv')
n_missings_each_col = df.apply(lambda x: x.isnull().sum()) # 每列缺省值计数
print(n_missings_each_col)
print(n_missings_each_col.argmax()) # 缺省值数最多列的列号


''' 42、各自列均值填充DataFrame中各自列缺省值 '''
df = pd.read_csv('datasets/Cars93_miss.csv')
df_out = df[['Min.Price', 'Max.Price']].apply(lambda x: x.fillna(x.mean()))
print(df_out.head())


''' 43、各自列均值、中值填充DataFrame中各自列缺省值(使用apply) '''
df = pd.read_csv('datasets/Cars93_miss.csv')
d = {'Min.Price': np.nanmean, 'Max.Price': np.nanmedian}
df[['Min.Price', 'Max.Price']] = df[['Min.Price', 'Max.Price']].apply(lambda x, d: x.fillna(d[x.name](x)), args=(d, ))
print(df[['Min.Price', 'Max.Price']])


''' 44、从DataFrame选择子DataFrame '''
df = pd.DataFrame(np.arange(20).reshape(-1, 5), columns=list('abcde'))
# print(df)
# 选择子DataFrame
print(type(df[['a']]))          # <class 'pandas.core.frame.DataFrame'>
print(type(df.loc[:, ['a']]))   # <class 'pandas.core.frame.DataFrame'>
print(type(df.iloc[:, [0]]))    # <class 'pandas.core.frame.DataFrame'>

# 选择Series
print(type(df.a))
print(type(df['a']))
print(type(df.loc[:, 'a']))
print(type(df.iloc[:, 1]))


''' 45、 改变DataFrame列顺序 '''
df = pd.DataFrame(np.arange(20).reshape(-1, 5), columns=list('abcde'))
# 方法1:传入一个list
df1= df[list('cbade')]
print(df1.head(2))
# 方法2:自定义函数
def switch_columns(df, col1=None, col2=None):
    colnames = df.columns.tolist()
    i1, i2 = colnames.index(col1), colnames.index(col2)
    colnames[i2], colnames[i1] = colnames[i1], colnames[i2]
    return df[colnames]
df2 = switch_columns(df, 'a', 'c')
print(df2.head(2))
# 方法3:
df3 = df[sorted(df.columns)]
print(df3.head(2))
# 方法4:
df4 = df.sort_index(axis=1, ascending=False)
print(df4.head(2))


''' 46、大DataFrame修改默认显示的行和列数 '''
df = pd.read_csv('datasets/Cars93_miss.csv')
pd.set_option('display.max_columns', 10)    #输出10列
pd.set_option('display.max_rows', 10)       #输出10行
print(df)


''' 47、DataFrame数据小数位数设置 '''
df = pd.DataFrame(np.random.random(4), columns=['random'])
print(df)
#方法1: Rounding
df1 = df.round(4)
print(df1)
#方法2: Use apply to change format
df3 = df.apply(lambda x: '%.4f' % x, axis=1)
print(df3)
df4 = df.applymap(lambda x: '%.4f' % x)
print(df4)
#方法3: Use set_option
df5 = pd.set_option('display.float_format', lambda x: '%.4f' % x)
print(df5)
#方法4: Assign display.float_format
pd.options.display.float_format = '{:.4f}'.format
print(df)


''' 48、 DataFrame数据小数转百分比显示 '''
df = pd.DataFrame(np.random.random(4), columns=['random'])
print(df)
df1 = df.applymap(lambda x: '%.2f%%' % (x*100))
# out = df.style.format({'random': '{0:.2%}'.format,})      # 这个不成功
print(df1)


''' 49、DataFrame数据每隔20行读取 '''
df = pd.read_csv('datasets/Cars93_miss.csv')
print(df.iloc[::20, :][['Manufacturer', 'Model', 'Type']])


''' 50、创建DataFrame主键 '''
df = pd.read_csv('datasets/Cars93_miss.csv', usecols=[0,1,2,3,5])
df[['Manufacturer', 'Model', 'Type']] = df[['Manufacturer', 'Model', 'Type']].fillna('missing')     # object列空值用字符串填充
df.index = df.Manufacturer + '_' + df.Model + '_' + df.Type     # 三列合并为index
print(df)
print(df.index.is_unique)       # True  判断index是否唯一


''' 51、获取DataFrame某一列中第n大的值索引 
Series.argsort(axis=0, kind='quicksort', order=None)  # 对series值进行排序的整数索引。
'''
df = pd.DataFrame(np.random.randint(1, 30, 21).reshape(-1,3), columns=list('abc'))
print(df['a'])
print(df['a'].sort_values())
print(df['a'].sort_values()[::-1])
print(df['a'].sort_values()[::-1][1:3].index)       # Int64Index([5, 0], dtype='int64')
print(df['a'].sort_values()[::-1][1:3].index[0])    # 5


''' 52、获取DataFrame某一列中第n大的值大于指定值的索引 '''
ser = pd.Series(np.random.randint(1, 100, 15))
print('ser: ', ser.tolist(), 'mean: ', round(ser.mean()))
print(np.where(ser > round(ser.mean()))[0])


''' 53、获取DataFrame中行和大于100的行 '''
df = pd.DataFrame(np.random.randint(10, 40, 60).reshape(-1, 4))
# 求行和
rowsums = df.apply(np.sum, axis=1)  # axis=1指定行
print(rowsums)
print(df.iloc[np.where(rowsums > 110)])


''' 54、 Series or DataFrame中使用分位数填充超限区域 
np.logspace(start=指数开始值,stop=指数结束值,num=个数,base=对数的底(默认为10), endpoint=包含结束值(默认包含))    # 对数等比数列
'''
#需求:使用0.05分位数和0.95分位数分别替换小于和大于该分位数的区域
ser = pd.Series(np.logspace(-2, 2, 30))     # 10**(-2)=0.01   10**2=100  
print(ser.round(4).tolist())
def cap_outliers(ser, low_perc, high_perc):
    low, high = ser.quantile([low_perc, high_perc])     # 指定分位数
    print(low_perc, '%ile: ', low, '|', high_perc, '%ile: ', high)
    ser[ser < low] = low
    ser[ser > high] = high
    return(ser)
capped_ser = cap_outliers(ser, .05, .95)
print(capped_ser.tolist())


''' 55、去除指定值将DataFrame转换为最大方阵 '''
df = pd.DataFrame(np.random.randint(-20, 50, 100).reshape(10,-1))
print(df)
#去除负值
arr = df[df > 0].values.flatten()       # numpy.ndarray.flatten(),即返回一个一维数组。大于0的元素
arr_qualified = arr[~np.isnan(arr)]     # 去除nan值,依然是一维数组
#寻找最大可能的方阵维度
n = int(np.floor(arr_qualified.shape[0]**.5))   # np.floor()返回不大于输入参数的最大整数,为浮点型
#方阵转换
top_indexes = np.argsort(arr_qualified)[::-1]
output = np.take(arr_qualified, sorted(top_indexes[:n**2])).reshape(n, -1)  # np.take(arr, indices)沿轴取数组中的元素,indices第几个。
print(output)


''' 56、DataFrame两行交换 '''
df = pd.DataFrame(np.arange(25).reshape(5, -1))
print(df)
def swap_rows(df, i1, i2):
    a, b = df.iloc[i1, :].copy(), df.iloc[i2, :].copy()
    df.iloc[i1, :], df.iloc[i2, :] = b, a
    return df
print(swap_rows(df, 1, 2))


''' 57、DataFrame逆序输出 '''
df = pd.DataFrame(np.arange(25).reshape(5, -1))
print(df)
#方法 1
df.iloc[::-1, :]
#方法 2
print(df.loc[df.index[::-1], :])


''' 58、DataFrame转对角矩阵 
pd.get_dummies()特征提取,one-hot encoding的基本思想:将离散型特征的每一种取值都看成一种状态,若你的这一特征中有N个不相同的取值,
                那么我们就可以将该特征抽象成N种不同的状态,one-hot编码保证了每一个取值只会使得一种状态处于“激活态”,
                也就是说这N种状态中只有一个状态位值为1,其他状态位都是0。
'''
df = pd.DataFrame(np.arange(25).reshape(5,-1), columns=list('abcde'))
print(df)
df_onehot = pd.concat([pd.get_dummies(df['a']), df[list('bcde')]], axis=1)
print(df_onehot)


''' 59、DataFrame那一列含有最大值最多的行 '''
df = pd.DataFrame(np.random.randint(1,100, 40).reshape(10, -1))
print(df)
print(df.apply(np.argmax, axis=1))
print(df.apply(np.argmax, axis=1).value_counts())
print(df.apply(np.argmax, axis=1).value_counts().index)
print('最大值最多的行: ', df.apply(np.argmax, axis=1).value_counts().index[0])

''' 60、DataFrame创建新列:每行为行号(按欧几里得距离而来) '''
df = pd.DataFrame(np.random.randint(1,100, 40).reshape(5, -1), columns=list('abcdefgh'), index=list('mnprs'))
print(df)
# init outputs
nearest_rows = []
nearest_distance = []
# iterate rows.
for i, row in df.iterrows():  # iterrows() 是在数据框中的行进行迭代的一个生成器,它返回每行的索引及一个包含行本身的对象。
    curr = row
    rest = df.drop(i)
    e_dists = {}  # init dict to store euclidean dists for current row.
    # iterate rest of rows for current row
    for j, contestant in rest.iterrows():
        # compute euclidean dist and update e_dists
        e_dists.update({j: round(np.linalg.norm(curr.values - contestant.values))})
    # update nearest row to current row and the distance value
    nearest_rows.append(max(e_dists, key=e_dists.get))
    nearest_distance.append(max(e_dists.values()))
df['nearest_row'] = nearest_rows
df['dist'] = nearest_distance
print(df)


''' 61、求DataFrame各列之间「最大」相关系数 '''
df = pd.DataFrame(np.random.randint(1,100, 80).reshape(8, -1), columns=list('pqrstuvwxy'), index=list('abcdefgh'))
print(df)
abs_corrmat = np.abs(df.corr())     # df.corr获取两列之间的相关性
print(abs_corrmat)
max_corr = abs_corrmat.apply(lambda x: sorted(x)[-2])
print('Maximum Correlation possible for each column: \n', np.round(max_corr.tolist(), 4))


''' 62、DataFrame创建一列:包含每行中最小值与最大值比值 '''
df = pd.DataFrame(np.random.randint(1,100, 80).reshape(8, -1))
print(df)
#方法 1
min_by_max = df.apply(lambda x: np.min(x)/np.max(x), axis=1)
print(min_by_max)
#方法 2
min_by_max = np.min(df, axis=1)/np.max(df, axis=1)
print(min_by_max)


''' 2.63、DataFrame创建一列:包含每行中第二大的值 '''
df = pd.DataFrame(np.random.randint(1,100, 80).reshape(8, -1))
print(df)
out = df.apply(lambda x: x.sort_values().unique()[-2], axis=1)
df['penultimate'] = out
print(df)


''' 64、DataFrame每列按特定方式归一化 '''
df = pd.DataFrame(np.random.randint(1,100, 80).reshape(8, -1))
print(df)
# 均值、标准差归一化
out1 = df.apply(lambda x: ((x - x.mean())/x.std()).round(2))
print('均值、标准差归一化:\n',out1)
# 最大最小值归一化
out2 = df.apply(lambda x: ((x.max() - x)/(x.max() - x.min())).round(2))
print('最大最小值归一化:\n', out2)  


''' 65、计算DataFrame每行与后一行的相关系数 '''
df = pd.DataFrame(np.random.randint(1,100, 80).reshape(8, -1))
print(df)
print([df.iloc[i].corr(df.iloc[i+1]).round(2) for i in range(df.shape[0])[:-1]])


''' 66、DataFrame对角线元素替换为0 '''
df = pd.DataFrame(np.random.randint(1,100, 100).reshape(10, -1))
print(df)
for i in range(df.shape[0]):
    df.iat[i, i] = 0
    df.iat[df.shape[0]-i-1, i] = 0
print(df)


''' 67、DataFrame按某列分组、提取某个分组 '''
df = pd.DataFrame({'col1': ['apple', 'banana', 'orange'] * 3,
                   'col2': np.random.rand(9),
                   'col3': np.random.randint(0, 15, 9)})
print(df)
df_grouped = df.groupby(['col1'])#按col1列分组
#获取指定分组,此处取apple组
# 方法 1
df1= df_grouped.get_group('apple')   # get_group()函数返回一个按照分组得到的DF对象。
print(df1)
# 方法 2
for i, dff in df_grouped:
    if i == 'apple':
        print(dff)


''' 68、DataFrame按另外列分组、提取当前列中指定值(看下方例子,需求不好描述) '''
df = pd.DataFrame({'fruit': ['apple', 'banana', 'orange'] * 3,
                   'taste': np.random.rand(9),
                   'price': np.random.randint(0, 15, 9)})
print(df)
df_grpd = df['taste'].groupby(df.fruit)     # taste值按fruit类别排序
print(df_grpd.get_group('banana'))                  # 获取fruit中的banana组
print(df_grpd.get_group('banana').sort_values())    # 对fruit中的banana组的值排序
print(df_grpd.get_group('banana').sort_values().iloc[-2])   # 对fruit中的banana组的值排序,取第二大值


''' 69、DataFrame分组(看下方例子,需求不好描述) '''
df = pd.DataFrame({'fruit': ['apple', 'banana', 'orange'] * 3,
                   'rating': np.random.rand(9),
                   'price': np.random.randint(0, 15, 9)})
print(df)
print(df.groupby('fruit', as_index=False))          #按fruit分组,as_index='False'指定'fruit'不做index
print(df.groupby('fruit', as_index=False)['price']) #按fruit分组、求每类fruit的均价
print(df.groupby('fruit', as_index=False)['price'].mean())#按fruit分组、求每类fruit的均价


''' 70、两个DataFrame使用类似SQL 中INNER JOIN拼接 '''
# Join dataframes df1 and df2 by ‘fruit-pazham’ and ‘weight-kilo’.
df1 = pd.DataFrame({
    'fruit': ['apple', 'banana', 'orange'] * 3,
    'weight': ['high', 'medium', 'low'] * 3,
    'price': np.random.randint(0, 15, 9)
})
df2 = pd.DataFrame({
    'pazham': ['apple', 'orange', 'pine'] * 2,
    'kilo': ['high', 'low'] * 3,
    'price': np.random.randint(0, 15, 6)
})
# Solution
df3 = pd.merge(df1, df2, how='inner', left_on=['fruit', 'weight'], right_on=['pazham', 'kilo'], suffixes=['_left', '_right'])
print(df3)


''' 71、移除DataFrame1中在DataFrame2出现的行 
Series.all(axis=0, bool_only=None, skipna=True, level=None, **kwargs)   # 函数返回是否所有元素都为True(可能在某个轴上)'''
df1 = pd.DataFrame({
    'fruit': ['apple', 'orange', 'banana'] * 3,
    'weight': ['high', 'medium', 'low'] * 3,
    'price': np.arange(9)   })
print(df1)
df2 = pd.DataFrame({
    'fruit': ['apple', 'orange', 'pine'] * 2,
    'weight': ['high', 'medium'] * 3,
    'price': np.arange(6)   })
print(df2)
print(df1[~df1.isin(df2).all(axis=1)])   # 1轴上


''' 72、取出DataFrame中两列值相等的行号 '''
df = pd.DataFrame({
    'fruit1': np.random.choice(['apple', 'orange', 'banana'], 10),
    'fruit2': np.random.choice(['apple', 'orange', 'banana'], 10)
})
print(df)
print(np.where(df.fruit1 == df.fruit2))


''' 73、DataFrame中新建两列:滞后列和提前列(看下方例子,需求BT) '''
df = pd.DataFrame(np.random.randint(1, 100, 20).reshape(-1, 4), columns=list('abcd'))
print(df)
df['a_lag1'] = df['a'].shift(1)         # a列每行值向后移一位
df['b_lead1'] = df['b'].shift(-1)       # b列每行值向前移一位
print(df)


''' 74、DataFrame中所有值出现频次统计 
numpy中的ravel()、flatten()、squeeze()都有将多维数组转换为一维数组的功能,区别:
ravel():如果没有必要,不会产生源数据的副本
flatten():返回源数据的副本,平时使用的时候flatten()更为合适
squeeze():只能对维数为1的维度降维
另外,reshape(-1)也可以“拉平”多维数组
'''
df = pd.DataFrame(np.random.randint(1, 10, 20).reshape(-1, 4), columns=list('abcd'))
print(df)
print(df.values.ravel())
print(pd.value_counts(df.values.ravel()))


''' 75、拆分DataFrame中某列文本为两列 '''
df = pd.DataFrame(["STD, City   State", "33, Kolkata    West Bengal", "44, Chennai  Tamil Nadu", "40, Hyderabad Telengana",
    "80, Bangalore    Karnataka"], columns=['row'])
print(df)
print(df.columns)
df_out = df.row.str.split(',|\t', expand=True)  # 拆分
new_header = df_out.iloc[0]                     # 第一列设置为标题
df_out = df_out[1:]
df_out.columns = new_header
print(df_out)
print(df_out.columns)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

岳涛@心馨电脑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值