[Home]
2 读取数据
-
表格类型数据读取
- 相关链接
[Home]
3 数据结构: DataFrame和Series
DataFrame
Series
一维数组对象,由一组数据(可以为不同类型)和一组相对应的数据标签(即索引)组成。
创建方法pd.Series
s = pd.Series([1,2,'a',[1,2,3]], index=['a', 'b', 'c', 'd'])
dict_data = {'Ohio':35000,'Texas':72000,'Orgeon':16000,'Utah':5000}
s= pd.Series(dict_data)
由标签索引或索引列表查询数据
s['a']
s[['b','a']]
表格型数据结构
创建方法pd.DataFrame
dictdata = {
'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Neveda'],
'year': [2000, 2001, 2002, 2001, 2002],
'pop': [1.5,1.7,3.6,4.3,9]
}
df = pd.DataFrame(dictdata, index=[1,2,3,4])
查询数据
df['year']
df[['year', 'pop']]
df.loc[1]
# 注意pandas中的切片是包含末尾指标的,这一点不同于Python
df.loc[1:3]
[Home]
4 数据查询的5种方法
Pandas主要查询方法中,本节主要讲述.loc方法。
# 得到单个值
df.loc["2018-01-03", "bWendu"]
# 得到Series
df.loc["2018-01-03", ["bWendu", "yWendu"]]
```
df.loc[["2018-01-03","2018-01-05"], "bWendu"]
```
# 既包含开始,也包含结束
# 行index按区间
df.loc["2018-01-03": "2018-01-05", "bWendu"]
# 列index按区间
df.loc["2018-01-03", "bWendu":"fengxiang"]
# 选出低于10度的记录
df.loc[df["yWendu"]<10,:]
# lamda函数
df.loc[lamda df : (df["bWendu"]<=30) & (df["yWndu"] > =15), :]
# 外部定义函数
def query_my_data(df):
...
df.loc[query_my_data,:]
[Home]
5 Pandas新增数据列
# "wencha"列原来是不存在
df.loc[:,"wencha"] = df["bWendu"] - df["yWndu"]
Apply a function along an axis of the DatatFrame.
Objects passed to the fuction are Series objects whose index is either the DataFrame’s index(axis=0) or the DataFrame’s columns (axis=1).
# 定义函数
def get_wendu_type(x):
if x["bWendu"] > 33:
return "高温"
if x["yWendu"] < -10:
return "低温"
return "常温"
# 注意需要设置axis==1,这是series的index是columns
df.loc[:, "wendu_type"] = df.apply(get_wendu_type, axis=1)
同时新增多个列。
Assign new columns to a DataFrame.
Rerturn a new object with all original columns in addition to new ones.
# 可以同时添加多个新的列
df.assign(
# 摄氏度转华氏度
yWendu_huashi = lambda x: x["yWendu"] * 9/5 + 32,
bWendu_huashi = lambda x: x["bWendu"] * 9/5 + 32,
)
按条件先选择数据,然后对这部分数据赋值新列
# 选创建空列
df["wencha_type"] = ""
df.loc[df["bWendu"]-df["yWendu"]>10,"wencha_type"]="温差大"
df.loc[df["bWendu"]-df["yWendu"]<=10,"wencha_type"]="温差正常“
[Home]
6 数据统计函数
# 提取所有数字列统计结果
df.describe()
# 查看单个Serices数据
df["bWendu"].mean()
# 最高温
df["bWendu"].max()
# 最低温
df["bWendu"].min()
# 列出包含的值(去掉重复的值)
df['fengxiang'].unique()
# 列出各值出现的次数
df['fengxiang'].value_counts()
df.cov()
df.corr()
df['aqi'].corr(df['bWendu'])
7 缺失值处理
场景:对于没有规则的数据做清洁和整理
处理前后对比
Pandas处理缺失值有3类函数
isnull
和notnull
:检测是否为空值,可用于dataframe和series;dropna
:丢弃、删除缺失值
# 筛选出分类不为空的行
studf.loc[studf['分类'].notnull(), :]
# 删除掉空列和空行
studf.dropna(axis="columns", how="all", inplace=True)
studf.dropna(axis="index", how="all", inplace=True)
# 将分数列为空的值填充为0
studf.fillna({"分数": 0})
studf.loc[:, '分数'] = studf['分数'].fillna(0)
# 将姓名的缺失值填弃
studf.loc[:, '姓名'] = studf['姓名'].fillna(method='ffill')
# 存成Excel表,不留存索引列
studf.to_excel(..., index=False)
[Home]
8 SettingsCopyWarning报警
Warning raised when trying to set on a copied slice from a DataFrame
.
核心要决:pandas的dataframe修改操作,只允许在源dataframe上进行,不得在copy上操作。
复现
condition = df['ymd'].str.startwith('20198-03']
df[condtion]['wen_cha']=df['bWendu']-df['yWendu']
# 产生SettingsCopyWarning报警
原因
df[condtion]['wen_cha']
相关于先get后set,此时get得到的是一个copy,而非一个view,则set时就会报警。pandas不允许在copy上进行修改。
修改
df.loc[condition, 'wen_cha'] = df['bWendu']- df['yWendu']
总结
[Home]
9 数据排序
用法:Series.sort_values(ascending=True,inplace=False)
# 数字Series的升序排列
df["aqi"].sort_values()
# 数字Series的降序排列
df["aqi"].sort_values(ascending=False)
# 除对数字排序外还可对中文的Series列进行排序
df["tianqi"].sort_values()
用法:DataFrame.sort_values(ascending=True,inplace=False)
单列排序
# 对单个列进行升序
df.sort_value(by="aqi")
# 对单个列进行降序
df.sort_values(by="aqi",ascending=False)
多列排序
# 按照空气质量等级、最高温度升序排列
df.sort_values(by=["aqiLevel","bWendu"])
# 按照空气质量等级、最高温度降序排列
df.sort_values(by=["aqiLevel","bWendu"],ascending=False)
# 分别对空气质量等级、最高温度指定升序排列或者降序排列
df.sort_values(by=["aqiLevel","bWendu"],ascending=[Ture,False])
10 字符串处理
# 获取erise的str属性
df["bWendu"].str
# 字符串替换函数
df["bWendu"].str.replace("C","")
# 判断是否为数字
df["bWendu"].str.isnumberic()
# 获取erise的str属性
condition=df["ymd"].str.startswith("2018-03")
df[condition].head()
# slice是切片语法
df["ymd"].str.replace("-","").str.slice[0:6]
# 添加新列
def get_nisnyueri(X):
year,month,day = X["ymd"].split("-")
return f"{year}年{month}月{day}日"
df["中文日期"] = df.apply(get_nianyueri,axis=1)
#去除插入列的文字
# 方法1:链式replace
df["中文日期"] .str.replace("年","") .str.replace("月","").str.replace("日","")
# 方法2:正则表达式替换
df["中文日期"] .str.replace("[年月日"],"")
11 理解axis
按照哪一个axis,就是这个axis要动起来(类似被for遍历),其它的axis保持不动
# 案例数据
df = pd.DataFrame(
np.arange(12).reshape(3,4),
columns = ["A","B","C","D"]
)
# 删除某一列
df.drop("A",axis = 1)
# 删除某一行
df.drop(1,axis = 0)
# axis = 0或axis = index
df.mean(axis = 0)
# axis = 1或axis = columns
df.mean(axis = 1)
# 增加列=其他四列的和
def get_sum_value(x):
return x["A"]+x["B"]+x["C"]+x["D"]
df["sum__value"] = df.apply(get_sum_value,axis = 1)
12 index用途
# 使用index方法查询
df.loc[800].head(5)
# 使用index排序后的查询
df_sorted = df_shuffile.sort_index(4)
# 对齐数据
s1=pd.Series([1,2,3],index=list("abc"))
s2=pd.Series([2,3,4],index=list("bcd"))
s1+s2
[Home]
13 Merge
pd.merge (left,right,on='sno')
# 数目以多的一边为准(数量会被复制)
pd.merge (left,right,on='sno')
# 数目以多的一边为准(数量会出现乘法)
pd.merge (left,right,on='sno')
# 左、右边都有key则出现在结果里
pd.merge (left,right,bow='inner')
# 左边的key输出结果,右边无法匹配则为Null
pd.merge (left,right,bow='left')
# 右边的key输出结果,左边无法匹配则为Null
pd.merge (left,right,bow='right')
# 左边、右边都出现结果,如果无法匹配则为Null
pd.merge (left,right,bow='outer')
# 左边、右边都出现结果,如果无法匹配则为Null
pd.merge (left,right,on='key')
#或者自己指定后缀
pd.merge (left,right,on='key',suffixes=('_left','_right'))
[Home]
14 Concat合并
pd.concat([df1,df2])
# ignore_index=True(忽略)
pd.concat([df1,df2],ignore_index=True)
# join=inner(过滤)
pd.concat([df1,df2],ignore_index=True,join="inner")
# 添加一列Series
s1=pd.series(list(range(4)),name="F")
pd.concat([df1,s1,axis=1)
# 添加多列Series
s2=df1.apply(lambda x:x["A"]+"_GG",axis=1)
# 列表只有series
pd.concat([s1,s2],axis=1)
# 列表混合顺序
pd.concat([s1,df1,s2],axis=1)
# 给一个dataframe添加dataframe
df1 = append(df2)
# ignore_index=True(忽略)
df1.append(df2,ignore_index=True)
# 一行一行为ataframe添加数据
df=pd.DataFrame(columns=["A"])
[Home]
15 批量拆分与合并Excel文件
[Home]
16 分组数据处理
#单个列groupby查询数据统计
df.groupby("A").sum()
#多个列groupby查询数据统计
df.groupby(["A","B"]).as_index=False)mean()
# 同时查看多种数据统计
df.groupby("A").agg([np.sum,np.mean,np.std])
# 查看单列统计结果
df.groupby("A").agg([np.sum,np.mean,np.std])["C"]
# 不同列使用不同聚合函数
df.groupby("A").agg(["C":np.sum,"D":np.mean])
# 遍历单个分组数据
g=df.groupby("A")
# 遍历多个列聚合分组
g=df.groupby(["A","B"])
# 查询group某几列生成series或者dataframe
g["C"]
[Home]
17 分层索引Multiindex
ser.reset_index()
# 第一层索引
ser.loc["BAIDU"]
# 多层索引,用元组形式筛选
ser.loc[("BAIDU","2019-10")]
# 筛选第二层索引
ser.loc[(:,"2019-10")]
stocks.sort_index(inplace = True)
stocks
stocks.loc[(slice(None),["2019-10-02","2019-10-03"]),:]
[Home]
18 map-apply-applymap数据处理
# 使用字典映射或者函数映射
Series.map(dict)或者Series.map(function)
#以将股票代码英文转换为中文名字为例
#使用dict
stocks["公司中文1"] = stocks["公司"].str.lower().map(dict_company_names)
#使用函function
stocks["公司中文2"] = stocks["公司"].map(lambda x:dict_company_names[x.lpwer()])
注意:
# Series.apply(function)
stocks["公司中文3"] = stocks["公司"].apply(lambda x:dict_company_names[x.lpwer()])
# DataFrame.apply(function)
stocks["公司中文4"] = stocks.apply(lambda x:dict_company_names[x["公司"].lpwer()],axis=1)
# 将数值取整用于元素
sub_df.applymap(lambda x:int())
# 直接修改原df的几列
stocks.loc[:,['收盘','开盘','高','低']]= sub_df.applymap(lambda x :int(x))
[Home]
19 groupby每个分组的apply
归一化的定义:
def_ratings_norm(df):
min_value = df["Rating"].min()
max_value = df["Rating"].max()
df["Rating_norm"] = df["Rating"].apply(lambda x : (x-min_value)/(max_value-min_value))
return df
Ratings = Ratings.groupby("UserID").apply(Ratings_norm)
Ratings[Ratings["UserID"].head]()
# 获取某年每个月温度最高的2天数据
def getWenduTopN(df,topn)
# df指每个月份分组groupby的df
return df.sort_values(by - "bWendu")[["ynd","bWendu"]][-topn:]
df.groupby("month").apply(getWenduTopN,topn = 2.head)
[Home]
20 使用stack和pivot实现数据透视
df_group = df.groupby([df["pdata"].dt.month,"Rating"])["UserID"].agg(pv = np.sum)
df_group.head(20)
df_stack = df_group.unstack()
# unstack与stack的互逆操作
df_stack.stack().head(20)
df_pivot = df_reset.pivot("pdata","Rating","pv")
#pivot方法相当于df使用set_index创建分层索引再调用unstack
stack:
unstack:
pivot:
[Home]
21 apply同时添加多列
如何方便启动jupyter中的notebook小知识:
首先打开目录(这个目录是数据和代码存放的位置),接着点路径位置所在的输入框,输入cmd,那么这个命令行就会再当前目录打开,打开终端的路径就是当前文件存放的路径,这个时候展现的内容就是刚才文件夹内的所有内容了。
# 同时添加多列数据
def_my_fun(row):
return row["bWendu"]-row["yWendu"],(row["bWendu"]+row["yWendu"])/2
df[["wencha","avg"]] = df.apply(my_func,axis = 1,result_type="expand")