pandas入门与进阶(一)

1.读取数据

import pandas as pd

# 使用pd.read_csv读取数据
fpath = "./datas/ml-latest-small/ratings.csv"
df = pd.read_csv(fpath)

# 读取txt文件,自己指定分隔符、列名
fpath = "./datas/crazyant/access_pvuv.txt"
df = pd.read_csv(
    fpath,
    sep="\t",
    header=None,
    names=['pdate', 'pv', 'uv']
)
# 如果读取文件没有列名(输出默认第一行内容为列名),
# 则需要给header=None同时names给自定义列名列表

# 读取excel文件
fpath = "./datas/crazyant/access_pvuv.xlsx"
df = pd.read_excel(fpath, skiprows=2)
# skiprows 忽略前面的2个空行

# 读取MySQL数据库
import pymysql
conn = pymysql.connect(
        host='127.0.0.1',
        user='root',
        password='test',
        database='test',
        charset='utf8'
    )
mysql_df = pd.read_sql("select * from table_name", con=conn)

2.查看数据集基本信息

# 查看数据类型
type(df)
# 查看前几行数据,默认前5行
df.head()
# 查看后几行数据
df.tail()
# 查看数据的形状,返回(行数、列数)
df.shape
# 数据各列名包含的数据计数
df.count()
# 查看列名列表
df.columns
# 查看索引列
df.index
# 查看每列的数据类型
df.dtypes
# 查看数据值
df.values
# 提取所有数字列统计结果
df.describe()
# 查看数据基本信息
df.info()

3.pandas数据结构分 DataFrame 和 Series

DataFrame是一个表格型的数据结构

	1. 每列可以是不同的值类型(数值、字符串、布尔值等)
	2. 既有行索引index,也有列索引columns
	3. 可以被看做由Series组成的字典
	4. 一行一列为Series,多行多列为DataFrame
# 创建 Series 数据
ser_data = [1, 'a', 5.2, 7]
ser = pd.Series(ser_data, index=['d','b','a','c'])
# 字典形式创建
ser_dict_data = {'Ohio':35,'Texas':72,'Oregon':16,'Utah':50}
ser2 = pd.Series(ser_dict_data )

# 为Series的列名赋值
ser.name = 'new_name'

# 字典形式创建 DataFrame
data={
        'state':['Ohio','Ohio','Ohio','Nevada','Nevada'],
        'year':[2000,2001,2002,2001,2002],
        'pop':[1.5,1.7,3.6,2.4,2.9]
    }
df = pd.DataFrame(data)

4.Pandas查询数据(推荐.loc,既能查询,又能覆盖写入)

  1. df是可以直接做条件筛选或切片操作的 df[ 条件或切片操作]
  2. df.loc方法,根据行、列的 标签值 查询
  3. df.iloc方法,根据行、列的 数字位置 查询----只能整数
  4. df.where方法
  5. df.query方法
# Series类型
df['bWendu']	
df.loc[:,'bWendu']

# DataFrame类型
df[['bWendu']]	
df.loc[:,['bWendu']]

1、使用单个label值查询数据

# 得到单个值
df.loc['2018-01-03', 'bWendu']
# 得到一个Series
df.loc['2018-01-03', ['bWendu', 'yWendu']]

2、使用值列表批量查询

# 得到Series
df.loc[['2018-01-03','2018-01-04','2018-01-05'], 'bWendu']
# 得到DataFrame
df.loc[['2018-01-03','2018-01-04','2018-01-05'], ['bWendu', 'yWendu']]

3、使用数值区间进行范围查询

# 行index按区间
df.loc['2018-01-03':'2018-01-05', 'bWendu']
# 列index按区间
df.loc['2018-01-03', 'bWendu':'fengxiang']
# 行和列都按区间查询
df.loc['2018-01-03':'2018-01-05', 'bWendu':'fengxiang']

4、使用条件表达式查询

## 查询最高温度小于30度,并且最低温度大于15度,并且是晴天,并且天气为优的数据
df.loc[(df["bWendu"]<=30) & (df["yWendu"]>=15) & (df["tianqi"]=='晴'), :]

5、调用函数查询

# 直接写lambda表达式
df.loc[lambda df : (df["bWendu"]<=30) & (df["yWendu"]>=15), :]

# 编写自己的函数,查询9月份,空气质量好的数据
def query_my_data(df):
    return df.index.str.startswith("2018-09") & (df["aqiLevel"]==1)
    
df.loc[query_my_data, :]

iloc() 和 at() 、iat()、ix()

# 取前两列
df.iloc[:, :2]
# 取前两行
df.iloc[:2, ]

df.iloc[0,2]
df.iloc[1:4,[0,2]]
df.iloc[[1,3,5],[0,2]]
df.iloc[[1,3,5],0:2]

# ix 的功能更加强大,参数既可以是索引,也可以是名称,相当于,loc和iloc的合体
df.ix[1:3,['a','b']]
df.ix[[1,3,5],['a','b']]

# at 根据指定行index及列label,快速定位DataFrame的某个元素,选择列时仅支持列名
df.at[3,'a']
# iat 与at的功能相同,只使用索引参数
df.iat[3, 0]
df.iat[3,'a']

5.新增数据列

  1. 直接赋值
df.loc[:, "wencha"] = df["bWendu"] - df["yWendu"]
  1. df.apply 方法
    Apply a function along an axis of the DataFrame.
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)
  1. df.assign 方法
    Assign new columns to a DataFrame.
    Returns 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
)
  1. 按条件选择分组分别赋值
# 先创建空列(这是第一种创建新列的方法)
df['wencha_type'] = ''

df.loc[df["bWendu"]-df["yWendu"]>10, "wencha_type"] = "温差大"
df.loc[df["bWendu"]-df["yWendu"]<=10, "wencha_type"] = "温差正常"

6.数据统计函数

  1. 协方差:衡量同向反向程度,如果协方差为正,说明X,Y同向变化,协方差越大说明同向程度越高;如果协方差为负,说明X,Y反向运动,协方差越小说明反向程度越高。
  2. 相关系数:衡量相似度程度,当他们的相关系数为1时,说明两个变量变化时的正向相似度最大,当相关系数为-1时,说明两个变量变化的反向相似度最大
# 一下子提取所有数字列统计结果
df.describe()
# 查看单个Series的数据
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.缺失值处理过程

  1. 步骤1:读取excel的时候,忽略前几个空行(也可利用dropna删除
    空行)
studf = pd.read_excel("./datas/student_excel/student_excel.xlsx", skiprows=2)
  1. 步骤2:检测数据空值
studf.isnull()
# 筛选没有空分数的所有行
studf.loc[studf["分数"].notnull(), :]
  1. 步骤3:删除掉全是空值的列
studf.dropna(axis="columns", how='all', inplace=True)

# axis : 删除行还是列,{0 或 ‘index’, 1 或 ‘columns’}, default 0
# how : any则任何值为空都删除,all则所有值都为空才删除
# inplace : True修改当前df,False返回新的df
  1. 步骤4:删除掉全是空值的行
studf.dropna(axis="index", how='all', inplace=True)
  1. 步骤5:填充应该有值的空值项
studf.loc[:, '分数'] = studf['分数'].fillna(value=0)
studf.loc[:, '姓名'] = studf['姓名'].fillna(method="ffill")

# value:用于填充的值,可以是单个值,或者字典(key是列名,value是值)
# method : 等于ffill使用前一个不为空的值填充(forword fill)
#          等于bfill使用后一个不为空的值填充(backword fill)
# axis : 按行还是列填充,{0 or ‘index’, 1 or ‘columns’}
# inplace : True修改当前df,False返回新的df
  1. 步骤6:保存处理清洗后的数据
studf.to_excel("./datas/student_excel/student_excel_clean.xlsx", index=False)

8.数据排序

  1. Series 排序:
    Series.sort_values(ascending=True, inplace=False)
df["aqi"].sort_values(ascending=False)
# ascending:默认为True升序排序,为False降序排序
# inplace:是否修改原始Series
  1. DataFrame 排序
    DataFrame.sort_values(by, ascending=True, inplace=False)
# 分别指定升序和降序
df.sort_values(by=["aqiLevel", "bWendu"], ascending=[True, False])
# by:字符串或者List<字符串>,单列排序或者多列排序
# ascending:bool或者List,升序还是降序,如果是list对应by的多列
# inplace:是否修改原始DataFrame

9.字符串处理

  1. 使用方法:先获取Series的str属性,然后在属性上调用函数;
  2. 只能在字符串列上使用,不能数字列上使用;
  3. Dataframe上没有str属性和处理方法,只有Series有
  4. Series.str并不是Python原生字符串,而是自己的一套方法,不过大部分和原生str很相似
# 获取Series的str属性,使用各种字符串处理函数

# 字符串替换函数
df["bWendu"].str.replace("℃", "")
# 判断是不是数字
df["bWendu"].str.isnumeric()
# 获取长度
df["bWendu"].str.len()
# 使用str的startswith、contains等得到bool的Series可以做条件查询

condition = df["ymd"].str.startswith("2018-03")
condition = df["ymd"].str.contains("2018")
df[condition].head()
# 多次str处理的链式操作

df["ymd"].str.replace("-", "").str.slice(0, 6)
# 等同于
# slice就是切片语法,可以直接用
df["ymd"].str.replace("-", "").str[0:6]
# 使用正则表达式的处理(2018年12月31日 --> 20181231)

# 方法1:链式replace
df["中文日期"].str.replace("年", "").str.replace("月","").str.replace("日", "")
# 方法2:正则表达式替换
df["中文日期"].str.replace("[年月日]", "")

10.处理日期时间数据

# 将日期列转换成pandas的日期
df.set_index(pd.to_datetime(df["ymd"]), inplace=True)
# DatetimeIndex是Timestamp的列表形式
df.index
df.index[0]

# 固定的某一天筛选
df.loc['2018-01-05']
# 日期区间筛选
df.loc['2018-01-05':'2018-01-10']
# 按月份前缀筛选
df.loc['2018-03']
# 按月份区间筛选
df.loc["2018-07":"2018-09"]
# 按年份前缀筛选
df.loc["2018"]

# 周、月、季度数字列表
df.index.week
df.index.month
df.index.quarter

# 统计每周、月、季度的数据
df.groupby(df.index.week)["bWendu"].max().plot()
df.groupby(df.index.month)["bWendu"].max().plot()
df.groupby(df.index.quarter)["bWendu"].max().plot()
  • 处理日期索引的缺失的一般方法
# 一. 使用pandas.reindex方法
## 1. 将日期列设为索引,再将索引变成日期索引
df_date = df.set_index("pdate")
df_date = df_date.set_index(pd.to_datetime(df_date.index))
## 2. 使用pandas.reindex填充缺失的索引,date_range函数可以设置periods参数
pdates = pd.date_range(start="2019-12-01", end="2019-12-05")	# 生成完整的日期序列
df_date_new = df_date.reindex(pdates, fill_value=0)

# 二. 使用pandas.resample方法
## 1. 先将索引变成日期索引
df_new2 = df.set_index(pd.to_datetime(df["pdate"])).drop("pdate", axis=1)
## 2. 使用dataframe的resample的方法按照天重采样
df_new2 = df_new2.resample("D").mean().fillna(0)
  • 说明:
    resample的含义:改变数据的时间频率

11.groupby分组

  • 所有的聚合统计,都是在dataframe和series上进行的
    1.常用用法
df.groupby('A').sum()	# 如果不是数值,会被直接忽略
df.groupby(['A','B']).mean()	# ('A','B')成对变成了二级索引
df.groupby(['A','B'], as_index=False).mean()
df.groupby('A').agg([np.sum, np.mean, np.std])

df.groupby('A')['C'].agg([np.sum, np.mean, np.std]) # 查看单列的结果数据统计
df.groupby('A').agg({"C":np.sum, "D":np.mean})	# 不同列使用不同的聚合函数

  1. 理解过程
# 1、遍历单个列聚合的分组
g = df.groupby('A')
g
for name,group in g:
    print(name)
    print(group)
    print()

bar
     A      B         C         D
1  bar    one -0.375789 -0.345869
3  bar  three -1.564748  0.081163
5  bar    two -0.202403  0.701301

foo
     A      B         C         D
0  foo    one  0.542903  0.788896
2  foo    two -0.903407  0.428031

g.get_group('bar')
# 2、遍历多个列聚合的分组
g = df.groupby(['A', 'B'])
# name是一个2个元素的tuple
for name,group in g:
    print(name)
    print(group)
    print()
g.get_group(('foo', 'one'))
g['C']
for name, group in g['C']:
    print(name)
    print(group)
    print(type(group))
    print()

12.groupby后其他列数据处理

# 1. 单列-单指标统计
df.groupby("MovieID")["Rating"].mean()
# 2. 单列-多指标统计(1)
df.groupby("MovieID")["Rating"].agg(
    mean="mean", max="max", min=np.min
)
# 2. 单列-多指标统计(2)
df.groupby("MovieID").agg(
    {"Rating":['mean', 'max', np.min]}
)
# 3. 多列-多指标统计(1)
df.groupby("MovieID").agg(
        rating_max=("Rating", "max"),
        user_count=("UserID", lambda x : x.nunique()),
        LTB=("LTB", (lambda x: ",".join(x.unique())))
        # 尤其对‘字符串’数据列这样处理
)
# 3. 多列-多指标统计(2)
df.groupby("MovieID").agg(
    {
        "Rating": ['mean', 'min', 'max'],
        "UserID": lambda x :x.nunique()
    }
)
.reset_index()
.rename(columns={"ymd":"月份"})

13. 按行遍历DataFrame的3种方法

# 1. df.iterrows()		慢
for idx, row in df.iterrows():
    print(idx, row)
    print(idx, row["A"], row["B"], row["C"], row["D"])

# 2. df.itertuples()	快
for row in df.itertuples():
    print(row)
    print(row.Index, row.A, row.B, row.C, row.D)
    
# 3. for+zip	快
for A, B in zip(df["A"], df["B"]):
    print(A, B)

14. DataFrame赋值方法

# 1. 索引或者标签修改值的位置
df.iloc[2,2] = 1111
df.loc['20130101','B'] = 2222
# 2.有条件赋值
df.B[df.A>4] = 0
df.col1[df.col1 =='a'] = 'm'
# 3. 按行或列
df['F'] = np.nan
# 4. 添加series序列
df['E'] = pd.Series([1,2,3,4,5,6], index=pd.date_range('20130101',periods=6)) 

15. 数据转换函数map、apply、applymap

  1. map:只用于Series,实现每个值->值的映射
  2. apply:用于Series实现每个值的处理,用于Dataframe实现某个轴的Series的处理
  3. applymap:只能用于DataFrame,用于处理该DataFrame的每个元素
  • map用于Series值的转换
# 将股票代码英文转换成中文名字
dict_company_names = {
    "bidu": "百度",
    "baba": "阿里巴巴",
    "iq": "爱奇艺", 
    "jd": "京东"
}
stocks["公司中文1"] = stocks["公司"].str.lower().map(dict_company_names)
# 或者
stocks["公司中文2"] = stocks["公司"].map(lambda x : dict_company_names[x.lower()])
  • apply用于Series和DataFrame的转换
# Series.apply(function), 函数的参数是每个值
stocks["公司中文3"] = stocks["公司"].apply(
    lambda x : dict_company_names[x.lower()])
    
# DataFrame.apply(function), 函数的参数是Series
stocks["公司中文4"] = stocks.apply(
    lambda x : dict_company_names[x["公司"].lower()], 
    axis=1)
  • applymap用于DataFrame所有值的转换
# 将这些数字取整数,应用于所有元素
sub_df.applymap(lambda x : int(x))
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值