Pandas系列基础知识以及DataFrame常用操作

一、pandas简介

①pandas是什么?

1、Pandas 是一个强大的分析结构化数据的工具集
2、它的使用基础是Numpy(提供高性能的矩阵运算)
3、用于数据挖掘和数据分析,同时也提供数据清洗功能

②pandas特性

1、快速高效的DataFrame对象,用于带有集成索引的数据处理
2、用于在内存数据结构和不同格式之间读取和写入数据的工具:csv和文本文件等
3、智能数据对齐和丢失数据的集成处理:在计算中实现基于标签的自动对齐,并轻松将杂乱数据处理为有序形式
4、灵活地重塑和旋转数据集
5、基于智能标签的切片,花式索引和大数据集子集
6、可以从数据结构中插入和删除列,以实现大小可变性
7、借助强大的分组引擎汇总或转换数据,从而允许对数据集进行拆分应用合并操作

③pandas中的主要数据结构

Series

它是一种类似于一维数组的对象,是由一组数据(各种Numpy数据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据也可产生简单的Series对象

DataFrame

DataFrame 是Pandas中的一个表格型的数据结构,包含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型等),DataFrame既有行索引也有列索引,可以被看做是由Series组成的字典。

二、Series

Series和Numpy中array非常类似,相当于是array的改进版,其中最重要的区别就是Series能够提供显示索引,从而为表结构的行标和列标提供了基础;

①通过数组或者字典创建Series

小提示:多数情况下,Series数据结构使我们直接从DataFrame数据结构中截取出来的Series。
Pandas 的Series对象是一个带索引数据构成的一维数组,其创建方法和array非常类似:通过pd.Series函数并输入一个序列来完成创建。
Series和array的最显著区别就在于,NumPy数组通过隐式定义的整数索引获取数值,而Pandas的Series对象用一种显式定义的索引与数值关联。显式索引的定义让 Series 对象拥有了更强的能力。例如,索引不再仅仅是整数,还可以是任意想要的类型。如果需要,完全可以用字符串定义索引:

# 通过数组创建Series
np.random.seed(1234)
arr = np.random.randint(1,10,5)
ser = pd.Series(arr, index = ['a','b','c','d','e'])
ser
# 通过字典创建Series
d = {"a":1,"b":2,"c":3}
ser2 = pd.Series(d)
ser2

②Series常用属性

Series 转化为array

data = pd.Series([1, 3, 2])
data_np = data.values

Series的name和rename

我们可以在创建Series时,为其命名。主要是跟DataFrame结合起来,这个名字,就相当于DataFrame的列名。

ser = pd.Series(np.random.randn(5), name='something')
ser.index
ser.name
ser.rename("数组",inplace=True)

③Series的特性

Series的数组特性:
1、Series可以进行索引和切片
2、Series与ndarray非常相似,是大多数Numoy函数的有效参数

ser[0]
ser[1:4]
ser[[1,3,4]]
ser[ser>6]
np.exp(ser)

Series的字典特性:
Series同时也像一个固定大小的dict,可以通过索引标签获取和设置值

ser["c"]
ser["c":"e"] # 可以索引到最后一个位置
ser[["a","c","d"]]
ser.get("a")
ser.get("k","没找到")

④Series的矢量化和标签对齐

矢量化操作:在进行数据分析时,通常没必要去使用循环,而是使用矢量化的操作方式
标签对齐:Series和ndarray之间的一个主要区别是,Series之间的操作会自动对齐基于标签的数据。

ser3 = pd.Series([1,2,3,4,5],index = ['a','b','c','d','e'])
ser5 = pd.Series([1,2,3,4,5],index = ['a','b','k','d','n'])
ser + ser3
ser + ser5

三、DataFrame

DataFrame创建函数格式如下:
df = pd.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
其中,data部分可以输入一维或二维结构数据,index代表行标,columns代表列标。并且和NumPy中array一样,也可以设置dtype属性。

①创建DataFrame

小提示:多数情况下,通过读取文件来创建DataFrame

# 通过数组创建dataframe
arrpd = np.random.randint(1,100,(3,7))
pd.DataFrame(arrpd, index=["a","c","b"],columns = ["A","B","C","D","E","F","G"])
# 通过字典创建DataFrame
dictpd = {"name":["zhangsan","lisi","wangwu"],"sold":[30000,20000,50000],"money":[6000,4000,10000]}
df1 = pd.DataFrame(dictpd)
df1
# 可以容忍缺失值
dicts = {"name":pd.Series(["zhangsan","lisi","wangwu"]),"sold":pd.Series([30000,20000]),"money":pd.Series([6000,4000,10000])}
df1 = pd.DataFrame(dicts)
df1

②DataFrame列操作

对于一个表结构数据来说,列的操作是最常用的操作之一。而由于DataFrame具备字典属性,因此列的选取,设置和删除列的工作原理与类似的 dict 操作相同。
增加列
1、DataFrame列的选取,设置和删除列的工作原理与类似的dict操作相同
2、insert方法插入列,指定插入列的位置
删除列
1、pop
2、drop
3、del

# 通过字典创建DataFrame
dictpd = {"name":["zhangsan","lisi","wangwu"],
          "sold":[30000,20000,50000],
          "money":[6000,4000,10000]}
df1 = pd.DataFrame(dictpd)
# 单独某一列的提取,或通过一个标量添加一整列信息
df1["wages"] = 2500 
# 通过其他列的运算得到新的一列
df1["contributions"] = df1["sold"] - df1["money"] - df1["wages"]
df1["sex"] = pd.Series(["famale","male","male"])
# insert插入列
df1.insert(6,"age",[25,27,30])
# df1.pop("age")
df1.drop(columns=["age","sex"],inplace = True)
df1

裴帅帅系列实例

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)
# 查询一列,结果是一个pd.Series
df['year']
# 查询多列,结果是一个pd.DataFrame
df[['year', 'pop']]
# 查询一行,结果是一个pd.Series
df.loc[1]
# 查询多行,结果是一个pd.DataFrame
# 注意这里的1:3,是包括3
df.loc[1:3]

③索引和选择

如果只索引行信息,所有列信息都保留,索引语法中的列索引信息可以省略。
如果只索引列信息,所有行信息都保留,索引语法中的行索引信息不可以被省略,写冒号加逗号表示所有行信息都保留。
.iloc和loc的一个区别是,进行切片时,前者是左闭右开,后者是左闭右闭
1、基于标签的索引
.loc是基于标签的索引,必须使用数据的标签属性,否则会返回一个异常。
基于标签索引的基本语法:
df.loc[行索引,列索引]

df1.loc[:,"name"]
df1.loc[0,"name":"wages"]
# 增加一行信息
df1.loc[3]=["lilei",60000,12000,2500,np.nan,"male",26]
df1.loc[[0,2]]
df1.loc[:,["name","sex"]]

2、基于位置的索引
.iloc是基于位置的索引,传入的参数为目标区域的位置索引。
基于位置索引的基本语法:
df.iloc[行索引,列索引]

df1.iloc[1]
df1.iloc[1,[0,2]]
df1.iloc[:,-1]
df1.iloc[1:3] # 基于位置的切片,终止值是切不到的;
df1.loc[1:2] #  基于标签的切片,终止值会被切到
df1.iloc[[1,2],[0,2,3]]

3、布尔型索引
使用布尔向量来过滤选取符合条件要求的数据

df1[df1.loc[:,"money"]>= 10000]
df1[df1.loc[:,"age"]>= 27]
# & 表示并且,两个条件必须都满足
# | 表示或者,满足任意条件都可以
df1[(df1.loc[:,"money"]>= 10000) & (df1.loc[:,"age"]>= 27)]
df1[(df1.loc[:,"money"]>= 10000) | (df1.loc[:,"age"]>= 27)]

④ Pandas使用df.loc查询数据的方法

df = pd.read_csv(r"C:\Users\happy\Desktop\dataset\ant/beijing_tianqi_2018.csv")
# 设定索引为日期,方便按日期筛选
df.set_index('ymd', inplace=True)
# 替换掉温度的后缀℃
df.loc[:, "bWendu"] = df["bWendu"].str.replace("℃", "").astype('int32')
df.loc[:, "yWendu"] = df["yWendu"].str.replace("℃", "").astype('int32')

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. 使用条件表达式查询

bool列表的长度得等于行数或者列数

# 简单条件查询,最低温度低于-10度的列表
df.loc[df["yWendu"]<-10, :]

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, :]

⑤ Pandas 新增/修改数据列

df = pd.read_csv(r"C:\Users\happy\Desktop\dataset\ant/beijing_tianqi_2018.csv")
# 设定索引为日期,方便按日期筛选
df.set_index('ymd', inplace=True)

1. 直接赋值

实例:清理温度列,变成数字类型
# 替换掉温度的后缀℃
df.loc[:, "bWendu"] = df["bWendu"].str.replace("℃", "").astype('int32')
df.loc[:, "yWendu"] = df["yWendu"].str.replace("℃", "").astype('int32')
# 实例:计算温差
# 注意,df["bWendu"]其实是一个Series,后面的减法返回的是Series
df.loc[:, "wencha"] = df["bWendu"] - df["yWendu"]

2. df.apply方法

Apply a function along an axis of the DataFrame.

Objects passed to the function are Series objects whose index is either the DataFrame’s index (axis=0) or the DataFrame’s columns (axis=1).

实例:添加一列温度类型:

  1. 如果最高温度大于33度就是高温
  2. 低于-10度是低温
  3. 否则是常温
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)
# 查看温度类型的计数
df["wendu_type"].value_counts()

3. df.assign方法

不修改原来的df

# 实例:将温度从摄氏度变成华氏度
# 可以同时添加多个新的列
df.assign(
    yWendu_huashi = lambda x : x["yWendu"] * 9 / 5 + 32,
    # 摄氏度转华氏度
    bWendu_huashi = lambda x : x["bWendu"] * 9 / 5 + 32
)

4. 按条件选择分组分别赋值

按条件先选择数据,然后对这部分数据赋值新列
实例:高低温差大于10度,则认为温差大

# 先创建空列(这是第一种创建新列的方法)
df['wencha_type'] = ''

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

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

df["wencha_type"].value_counts()

⑥ Pandas 数据统计函数

df = pd.read_csv(r"C:\Users\happy\Desktop\dataset\ant/beijing_tianqi_2018.csv")
# 设定索引为日期,方便按日期筛选
df.set_index('ymd', inplace=True)
# 替换掉温度的后缀℃
df.loc[:, "bWendu"] = df["bWendu"].str.replace("℃", "").astype('int32')
df.loc[:, "yWendu"] = df["yWendu"].str.replace("℃", "").astype('int32')

1. 汇总类统计

# 一下子提取所有数字列统计结果
df.describe()
df.describe([0.01,0.05,0.1,0.25,0.5,0.75,0.9,0.99]).T
## 查看单个Series的数据
df["bWendu"].mean()
# 最高温
df["bWendu"].max()
# 最低温
df["bWendu"].min()

2. 唯一去重和按值计数

唯一性去重,一般不用于数值列,而是枚举、分类列

df["fengxiang"].unique()
df["tianqi"].unique()
df["fengli"].unique()

按值计数

df["fengxiang"].value_counts()
df["tianqi"].value_counts()
df["fengli"].value_counts()

3. 相关系数和协方差

  1. 协方差:衡量同向反向程度,如果协方差为正,说明X,Y同向变化,协方差越大说明同向程度越高;如果协方差为负,说明X,Y反向运动,协方差越小说明反向程度越高。
  2. 相关系数:衡量相似度程度,当他们的相关系数为1时,说明两个变量变化时的正向相似度最大,当相关系数为-1时,说明两个变量变化的反向相似度最大
# 协方差矩阵:
df.cov()
# 相关系数矩阵
df.corr()
# 单独查看空气质量和最高温度的相关系数
df["aqi"].corr(df["bWendu"])
# 空气质量和温差的相关系数
df["aqi"].corr(df["bWendu"]-df["yWendu"])

四、DataFrame常用操作

①数据查看和描述

查看数据形状 df.shape
查看数据详细信息 df.info()
简单描述分析 df.describe()

df = pd.read_csv(r"C:\Users\happy\Desktop\sales.txt",sep = ' ',index_col = 0)
df.index = ["001","002","003","004","005","006","007"]
df.shape  # 查看数据框的形状
df.head(n=5)
df.tail(n =5)
df.index  # 查看行索引
df.columns # 查看列索引
df.info() # 查看数据框的详细信息
df.describe() # 进行简单的描述统计
df.sort_index(ascending = False) # 默认升序排序
df.sort_values(by=["销售业绩","社保金额"], ascending = [True, False])

裴帅帅系列实例

ratings = pd.read_csv(r"C:\Users\happy\Desktop\dataset\ant\ratings.csv")
# 查看前几行数据
ratings.head()
# 查看数据的形状,返回(行数、列数)
ratings.shape
# 查看列名列表
ratings.columns
# 查看索引列
ratings.index
# 查看每列的数据类型
ratings.dtypes

②缺失值处理

缺失值查看 df.isnull()
填补缺失值 fillna() replace()
删除缺失值 df,dropna()

df.iloc[[0,1,3,5],[1,2,4,6,9]] = np.nan  # 人为制造缺失值
# 查看缺失值数量
df.isnull().sum()
# 查看缺失值比例
df.isnull().mean()
df.loc[:,"员工等级"].value_counts()
df.fillna(df.mean())
df.loc[:,"员工状态"].fillna("在职") # 对指定列进行填充
df.fillna(method = "ffill")
df.replace(np.nan, df.median())
df.dropna() # 默认按照行进行删除

裴帅帅系列
Pandas使用这些函数处理缺失值:

  • isnull和notnull:检测是否是空值,可用于df和series
  • dropna:丢弃、删除缺失值
    • axis : 删除行还是列,{0 or ‘index’, 1 or ‘columns’}, default 0
    • how : 如果等于any则任何值为空都删除,如果等于all则所有值都为空才删除
    • inplace : 如果为True则修改当前df,否则返回新的df
  • fillna:填充空值
    • value:用于填充的值,可以是单个值,或者字典(key是列名,value是值)
    • method : 等于ffill使用前一个不为空的值填充forword fill;等于bfill使用后一个不为空的值填充backword fill
    • axis : 按行还是列填充,{0 or ‘index’, 1 or ‘columns’}
    • inplace : 如果为True则修改当前df,否则返回新的df
# 删除掉全是空值的列
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)
# 将姓名的缺失值填充
# 使用前面的有效值填充,用ffill:forward fill
studf.loc[:, '姓名'] = studf['姓名'].fillna(method="ffill")

③数据合并

pd.concat()
pd.merge()

df = pd.read_csv(r"C:\Users\happy\Desktop\sales.txt",sep = ' ',index_col = 0)
df.index = ["001","002","003","004","005","006","007"]
df_1 = df.iloc[:4]
df_2 = df.iloc[4:]
df_all = pd.concat([df_1,df_2],ignore_index = True)
df_3 = df.iloc[:,:7]
df_4 = df.iloc[:,[0,7,8,9,10]]
df_con = pd.concat([df_3,df_4],axis = 1,keys=["df_3","df_4"],names=["来源表","索引"])
df_mer = pd.merge(df_3,df_4,on="员工姓名")
df_mer

④分组运算

df.groupby()

df = pd.read_csv(r"C:\Users\happy\Desktop\sales.txt",sep = ' ',index_col = 0)
df.index = ["001","002","003","004","005","006","007"]
gp1=df.groupby("性别")
gp2 = df.groupby("员工等级")
gp1.size()
gp1.mean()
gp1["销售业绩"].mean()
gp3 = df.groupby(["性别","员工等级"],as_index=False)
gp3.mean()
gp2.agg({"销售业绩":np.mean,"提成收入":np.std})
gpp = gp2["销售业绩"].agg([np.mean,np.std])
gpp.rename(columns={"mean":"平均销售额","std":"标准差"})

⑤数据透视表

pd.pivot_table()

df = pd.read_csv(r"C:\Users\happy\Desktop\sales.txt",sep = ' ',index_col = 0)
df.index = ["001","002","003","004","005","006","007"]
pd.pivot_table(df, values="创造收益",index="员工状态",columns="员工等级",aggfunc=np.sum)
pd.pivot_table(df, values=["创造收益","销售业绩"],index="员工状态",columns="员工等级",aggfunc=np.sum)

⑥数据的读入和导出

如果目标文件和当前py文件在同一个路径下,可以直接写文件名,如果不在,需要写文件路径。
pd.read_csv() 读取CSV和txt
pd.read_excel() 读取excel
df.to_excel() 输出Excel
df.to_csv() 输出CSV和Txt

# 读入数据的第一列为索引列
adult_data = pd.read_csv(r"C:\Users\happy\Desktop\adult_data_pytorch.csv", index_col = 0 )
# 第一行不是列索引时
df1 = pd.read_csv("file1.csv", header = None)
df1.columns = ['a', 'b', 'c', 'd', 'e']
df = pd.read_csv(r"C:\Users\happy\Desktop\sales.txt",sep = ' ',index_col = 0)
df.index = ["001","002","003","004","005","006","007"]
df.to_csv(r"C:\Users\happy\Desktop\销售明细.csv",encoding="utf-8_sig")

⑦DataFrame转Numpy

arrpd = np.random.randint(1,100,(3,7))
arrpd = pd.DataFrame(arrpd, index=["a","c","b"],columns = ["A","B","C","D","E","F","G"])
arrpd
arr = arrpd.values
arr

⑧DataFrame中修改满足某些条件的值

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
import pandas as pd
arrpd = np.random.randint(1,100,(3,7))
arrpd = pd.DataFrame(arrpd, index=["a","c","b"],columns = ["A","B","C","D","E","F","G"])
arrpd
arrpd.loc[arrpd["G"]>50,"G"] = 100
arrpd

pandas where函数用法
Series.where(cond, other=nan, inplace=False, axis=None, level=None, errors=‘raise’, try_cast=False, raise_on_error=None)
如果 cond 为真,保持原来的值,否则替换为other, inplace为真标识在原数据上操作,为False标识在原数据的copy上操作。
other must be the same shape as self: other的形状必须与self相同。
mask 函数和 where 作用刚好相反。

from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"
import pandas as pd
arrpd = np.random.randint(1,100,(3,7))
arrpd = pd.DataFrame(arrpd, index=["a","c","b"],columns = ["A","B","C","D","E","F","G"])
arrpd
arrpd.iloc[:,-1] = arrpd.iloc[:,-1].where(arrpd.iloc[:,-1]<30,200)
arrpd
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值