#%% md
### series的创建
#%%
import string
import pandas as pd
import numpy as np
from pandas.core.methods.selectn import DataFrame
#%%
t = pd.Series([18, 53, 32, 24, 12])
print(type(t))
print(t)
#%%
t = pd.Series(np.arange(10),index=list(string.ascii_uppercase[:10]))
print(t)
#%%
t1 = pd.Series([1,23,45,2,1],index=['a', 'b', 'c', 'd', 'e'])
t1 = pd.Series([1,23,45,2,1],index=list('abcde'))
print(t1)
print(t1.astype(float))
#%%
temp_dict = {'name':'xiao_hong','age':30,'tel':'10086'}
t2 = pd.Series(temp_dict)
print(t2)
#%%
a = {string.ascii_uppercase[i]:i for i in range(10)}
t = pd.Series(a,index=list(string.ascii_uppercase[5:15]))
print(t)
# 重新给其指定其他的索引之后,如果能够对应上,就取其值,如果不能,就为Nan
# numpy中nan为float,pandas会自动根据数据类更改series的dtype类型
# 目前为float
print(t.dtype)
#%% md
### series的索引
#%%
# 标签索引
print(t2)
print('*'*50)
print(t2['age'])
print(t2[['age','tel']])
#%%
# 切片
print(t2[:2])
print('*'*50)
#%%
#新版位置索引要用iloc函数不能直接使用t2[1]
print(t2.iloc[1])
#%%
# []/.loc(严格索引),索引不存在时直接抛KeyError
# .reindex()/.get()(宽松索引),不报错
print(t2.get('ages'))
#%%
t3 = pd.Series([1,6,3,4,2,5,7,8])
print(t3[t3>3])
#%%
# 索引的值0
print(t2.index)
print(type(t2.index))
print(len(t2.index))
print(list(t2.index))
print(list(t2.index)[:2])
#%%
print(t3.values)
#%% md
### where等切片方法
#%%
t3 = pd.Series([1,6,3,4,2,5,7,8])
print(t3.where(t3>3)) # 小于3的全部变成nan
print(t3.mask(t3>3)) # 大于3的全部变成nan
print(t3.where(t3>3,7)) # 小于3的全部变成7
#%%
print(t3.clip(3,4)) #小于3的变成3,大于4的变成4
#%% md
### dataframe的创建
#%%
pd. DataFrame(np.arange(4,16).reshape(3,4))#有横列两种索引 ,1是列索引,0是横索引
#%%
pd.DataFrame(np.arange(12).reshape(3,4),index=list("abc"),columns=list("WXYZ"))
#%%
d1 ={"name":["xiaoming","xiaogang"],"age": [20,32],"tel": [10086,10010]}
t4 = pd. DataFrame(d1)
print(t4)
print(type(t4))
#%%
d2 =[{"name":"xiao_hong","age":32,"tel":10010}, {"name":"xiao_gang","tel":10000}, {"name":"xiao_wang","age":22}]
t5 = pd.DataFrame(d2)
print(t5)
#%% md
### dataframe的基础属性
#%%
# DataFrame的基础属性
# df.shape # 行数 列数
# df.dtypes # 列数据类型
# df.ndim #数据维度
# df.index #行索引
# df.columns # 列索引
# df.values #对象值,二维ndarray数组
#
# DataFrame整体情况查询
# df.head(3)#显示头部几行,默认5行
# df.tail(3)#显示末尾几行,默认5行
# df.info()#相关信息概览:行数,列数,列索引,列非空值个数,列类型,列类型,内存占用
# df.describe(),#快速综合统计结果:计数,均值,标准差,最大值,四分位数,最小值
print(t5)
#%%
print(t5.index)
print(t5.columns)
print(t5.values)
print(t5.shape)
print(t5.dtypes)
#%%
print(t5.info())
print('*'*60)
print(t5.describe())
#%% md
### dataframe的索引和复合索引
#%%
# 1. df.loc 通过标签索引(行索引)数据,不加loc默认是上方的列索引
# 2. df.iloc 通过行位置获取数据
#%%
t3 = pd.DataFrame(np.arange(12).reshape(3,4),index=list("abc"),columns=list("WXYZ"))
print(t3)
#%%
print(t3.loc['a','Z'])
print('*'*20)
print(t3.loc['a'])
print('*'*20)
print(t3.loc[:,'Y'])
#%%
print('*'*20)
print(t3.loc[['a','c']])
print('*'*20)
print(t3.loc[:,['X','Y']])
print('*'*20)
print(t3.loc[['b','c'],['X','Y']])
#%%
print(t3.iloc[:,[2,1]])
t3.iloc[1:,:2] = np.nan
print(t3) #自动转换为float
#%%
# bool索引
print(t3[t3['Y']>5])
#%%
df1 = pd.DataFrame(np.ones(8).reshape(2,4),index=list("ab"),columns=list("abcd"))
print(df1)
# reindex()添加index和改变index位置,原来没有的索引的所有值为nan
print(df1.reindex(["100", "c","b"]))
# set_index()把原来的一列值当索引
df1["a"]=[100,1]
print(df1.set_index("a"))
print(df1.set_index("a",drop=False))#drop为True时会把原来的列删除
print(df1.set_index("b").index.unique())#除去重复索引
print(df1.set_index(["a","b"]))
print(df1.set_index(["a","b"]).index)#两个以上的索引是复合索引
#%%
# 复合索引
a = pd.DataFrame({'a':range(7),'b':range(7,0,-1),'c':['one','one','one','two','two','two','two'],'d': list("hjklmno")})
print(a)
b1 = a.set_index (["c","d"])
b2 = a.set_index (["d","c"])
print("b1:\n",b1)
print("b2:\n",b2)
# 取到b1中a下方的1的索引方法
c=b1["a"]
print(c)
print("取到b1中a下方的1的索引方法\n",c["one"]["j"])
# 在b2中把所有one的值取出来(可以先用swaplevel()把b2转变为b1)
print("在b2中把所有one的值取出来\n",b2.swaplevel().loc["one"])#swaplevel可以将两个索引的层级交换,默认情况交换最后两个
#%%
# 在b2中只取a下方的3这一个数据
print(b2.loc["l"].loc["two"]["a"])
#%% md
### 缺失数据处理
#%%
d2 =[{"name":"xiao_hong","age":32,"tel":10010}, {"name":"xiao_gang","tel":10000}, {"name":"xiao_wang","age":22}]
t5 = pd.DataFrame(d2)
print(t5)
print(pd.isnull(t5))
print(pd.notnull(t5))
print(t5[pd.notnull(t5['age'])]) # 输出age里面没有nan的行
#%%
# dropna删除有nan的行或列how用来判断是否符合条件
dn = t3.dropna(axis=0,how='all')
print(dn)
dn = t3.dropna(axis=0,how='any')
print(dn)
dn = t3.dropna(axis=1,how='any')
print(dn)
#%%
# inplace对nan进行原地修改(不能把修改后数据传入给其他变量)
t3.dropna(axis=0,how='any',inplace=True)
print(t3)
#%%
# 对nan进行填充
print(t5)
print(t5.fillna(20))
#%%
# 给t5的age里面的nan填入t5.[age]的平均数
print(t5['age'].mean())
print(t5['age'].fillna(t5['age'].mean()))
print(t5['tel'].fillna(t5['tel'].mean()))
#%%
# 对数据等于0的处理方式
# t[t==0] = np.nan
# 只对异常数据操作,因为0会参与平均数计算,而nan不会
#%% md
### 统计方法
#%%
# tolist() 是 NumPy 数组(ndarray) 和 Pandas 数据结构(如 Series、DataFrame) 中用于将数组 / 表格数据转换为 Python 原生列表的方法。
# unique() 是 NumPy 和 Pandas 中用于提取数据中唯一值(去重) 的方法,能返回数据中不重复的元素,且默认按首次出现的顺序排列(Pandas)或升序排列(NumPy)
# 在一串数据中去除重复数据并且统计总数
# len(set(df.["数据名称"].tolist()))
# len(df["数据名称"].unique())
# 一组不止一个数据并且每组数据由, 隔开并
# list_1 = df.["数据名称"].str.split(",").tolist() # 一组数据生成一个列表
# list_2 = [i for j in list_1 for i in j] # 把每个列表的数据转换到一个列表
# sum = len(set(list_2))
#%%
# 数据合并
# join
df1 = pd.DataFrame(np.ones(12).reshape(3,4),index=list("ABC"),columns=list("1XYZ"))
df2 = pd.DataFrame(np.ones(12).reshape(2,6),index=list("AD"))
print(df1.join(df2))
print(df2.join(df1))
# 谁在前面以设谁为主,把相同列合并,没有的删除
#%%
# merge
d1 = pd.DataFrame({"M":[1,1,1], "N":[1,1,1], "O":["a","b","c"], "P":[1,1,1]},
index=list("ABC"))
print(d1)
d2 = pd.DataFrame(np.zeros(10).reshape(2,5),index=list("AB"),columns=list("VWXYZ")).astype(object)
d2.loc["A","X"]="c"
d2.loc["B","X"]="d"
print(d2)
print("*"*50)
print(d1.merge(d2,left_on="O",right_on="X"))
print("*"*50)
print(d1.merge(d2,left_on="O",right_on="X",how="inner"))
print("*"*50)
print(d1.merge(d2,left_on="O",right_on="X",how="outer"))
print("*"*50)
print(d1.merge(d2,left_on="O",right_on="X",how="left"))
print("*"*50)
print(d1.merge(d2,left_on="O",right_on="X",how="right"))
# 默认方式为inner,按照on后面的进行合并,如果相同列有相同的值则把这一行保留
# orter是指把两个缺失的地方用nan保留,将相同列有相同的值的这一列合并
# left是保留前面d1全部列,把d2中相同列有相同的值则把这一行保留,其他删除,合并,每一行缺失填nan
# right是保留前面d2全部列,把d1中相同列有相同的值则把这一行保留,其他删除,合并,每一行缺失填nan
#%%
# 分组与聚合
# df.groupby(分组列)[目标列].聚合函数()
print(d1)
# grouped = d1.groupby(by="O")
# print(grouped)
# 返回一个DataFrameGroupBY对象
# 可以进行遍历,i是指by后面的""里面的那一列在每一行的值,j是每一列的值
# for i,j in grouped:
# print('i的值',i,'\n',j,type(j))
# 统计
# count分组中非NA值的数量
# sum非NA值的和
# mean非NA值的平均值
# median非NA值的算术中位数
# std. var无偏(分母为n-1)标准差和方差
# min, max非NA值的最小值和最大值
# print(grouped["M"].count())
# 按多个条件分组
grouped = d1["P"].groupby(by=[d1["O"],d1["M"]]).count()
print(grouped)
#%% md
### 其他方法
#%%
# cat
# 实现元素级的字符串连接操作,可指定分隔符
# contains
# 返回表示各字符串是否含有指定模式的布尔型数组
# count
# 模式的出现次数
# endswith. startswith
# 相当于对各个元素执行x.endswith(pattern)或x.startswith(pattern)
# findall
# 计算各字符串的模式列表
# get
# 获取各元素的第i个字符
# join
# 根据指定的分隔符将Series中各元素的字符串连接起来
# len
# 计算各字符串的长度
# lower, upper
# 转换大小写。相当于对各个元素执行x.lower()或x.upper()
# match
# 根据指定的正则表达式对各个元素执行re.match
# pad
# 在字符串的左边、右边或左右两边添加空白符
# center
# 相当于pad(side='both')
# repeat
# 重复值。例如,s.str.repeat(3)相当于对各个字符串执行x*3
# *replace
# 用指定字符串替换找到的模式
# slice
# 对Series中的各个字符串进行子串截取
# *split
# 根据分隔符或正则表达式对字符串进行拆分
# strip. rstrip. Istrip
# 去除空白符,包括换行符。相当于对各个元素执行x.strip() x.rstrip(). x.Istrip()