简介

DataFrame 一个表格型的数据结构,既有行标签(index),又有列标签(columns),它也被称异构数据表,所谓异构,指的是表格中每列的数据类型可以不同,比如可以是字符串、整型或者浮点型等。其结构图示意图,如下所示:

表格中展示了某个销售团队个人信息和绩效评级(rating)的相关数据。数据以行和列形式来表示,其中每一列表示一个属性,而每一行表示一个条目的信息。

DataFrame 的每一行数据都可以看成一个 Series 结构,只不过,DataFrame 为这些行中每个数据值增加了一个列标签。因此 DataFrame 其实是从 Series 的基础上演变而来。在数据分析任务中 DataFrame 的应用非常广泛,因为它描述数据的更为清晰、直观。
同 Series 一样,DataFrame 自带行标签索引,默认为“隐式索引”即从 0 开始依次递增,行标签与 DataFrame 中的数据项一一对应。

下面对 DataFrame 数据结构的特点做简单地总结,如下所示:

  • DataFrame 每一列的标签值允许使用不同的数据类型;
  • DataFrame 是表格型的数据结构,具有行和列;
  • DataFrame 中的每个数据值都可以被修改;
  • DataFrame 结构的行数、列数允许增加或者删除;
  • DataFrame 有两个方向的标签轴,分别是行标签和列标签;
  • DataFrame 可以对行和列执行算术运算。

创建DataFrame对象

基本语法

import pandas as pd
pd.DataFrame( data, index, columns, dtype, copy)

参数说明

参数名称

说明

data

输入的数据,可以是 ndarray,series,list,dict,标量以及一个 DataFrame。

index

行标签,如果没有传递 index 值,则默认行标签是 np.arange(n),n 代表 data 的元素个数。

columns

列标签,如果没有传递 columns 值,则默认列标签是 np.arange(n)。

dtype

dtype表示每一列的数据类型。

copy

默认为 False,表示复制数据 data。

事先说明

由于我是在jupyter notebook上写的代码,先导入库,后面写代码就不需要导入了。所以下面所有的代码,都是没有导入库。如果要copy的话,请加上下面的代码。

# 导入库

import pandas as pd
import numpy as np
import matplotlib

列表创建DataFrame对象

# 列表创建DATaFrame对象
# 单一列表

data=np.arange(5)
df=pd.DataFrame(data)
print(df)

嵌套列表创建

# 使用嵌套列表创建DataFrame对象

data=[['tom',10],['marry',20],['bill',30]]
df=pd.DataFrame(data,columns=['name','age'])
print(df)

字典嵌套列表创建

数据data字典中,键对应的值的元素长度必须相等(也就是列表长度相同)

# 字典嵌套列表创建

data={"name":["Alex","Biil","Amy"],"age":[10,20,30]}
df=pd.DataFrame(data)
print(df)

字典嵌套列表,自定义行标签

# 字典嵌套列表,自定义行标签

data={"name":["Alex","Biil","Amy"],"age":[10,20,30]}
index=["num1","num2","num3"]
df=pd.DataFrame(data,index=index)
print(df)

列表嵌套字典创建

列表嵌套字典可以作为输入数据传递给 DataFrame 构造函数。默认情况下,字典的键被用作列名。

# 列表嵌套字典创建

data = [{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}]
df = pd.DataFrame(data)
print(df)

注意:如果其中某个元素值缺失,也就是字典的 key 无法找到对应的 value,将使用 NaN 代替。

字典嵌套列表,自定义行/列标签

# 字典嵌套列表以及行,列索引表创建一个DataFrame对象

data = [{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}]
df1 = pd.DataFrame(data, index=['first', 'second'], columns=['a', 'b'])
df2 = pd.DataFrame(data, index=['first', 'second'], columns=['a', 'b1'])
df3 = pd.DataFrame(data, index=['first', 'second'], columns=['a', 'b','c'])
print(df1)
print("-"*50)
print(df2)
print("-"*50)
print(df3)

以字典形式的Series创建

传递一个字典形式的 Series,从而创建一个 DataFrame 对象,其输出结果的行索引是所有 index 的合集。

# 以字典形式的Series创建

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print(df)

注意:对于 one 列而言,此处虽然显示了行索引 'd',但由于没有与其对应的值,所以它的值为 NaN。

总结

创建的方法有很多种,这里只是列举几种常见常用的。很多人容易被列表和字典两种类型的嵌套的搞混,一开始我也看的非常迷茫,后来看出一点规律了。

  • 列表[]里面是一行数据,字典{}里面是一列数据。
  • 字典里的键就是DataFrame里的列标签
  • 每多一个嵌套列表就多一行数据,每多一个嵌套字典就多一列数据

列索引操作DataFrame

DataFrame 可以使用列索(columns index)引来完成数据的选取、添加和删除操作。下面依次对这些操作进行介绍。

列索引选取数据列

# 使用列索引实现数据获取

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print(df ['one'])

列索引添加数据

# 使用列索引添加数据

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)

#使用df['列']=值,插入新的数据列
df['three']=pd.Series([10,20,30],index=['a','b','c'])
print(df)

#将已经存在的数据列做相加运算
df['four']=df['one']+df['three']
print(df)

# 使用insert方法插入新的列

info=[['Jack',18],['Helen',19],['John',17]]
df=pd.DataFrame(info,columns=['name','age'])
print(df)
print("-"*50)

#注意是column参数
#数值1代表插入到columns列表的索引位置
df.insert(1,column='score',value=[91,90,75])
print(df)
  • 使用列标签可以直接添加数据,只不过只能添加在末尾
  • 使用insert添加数据,可以指定添加在哪一列

列索引删除数据列

# 使用del和pop删除数据列

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd']),
   'three' : pd.Series([10,20,30], index=['a','b','c'])}
df = pd.DataFrame(d)
print ("Our dataframe is:")
print(df)
print("-"*50)

#使用del删除
del df['one']
print(df)
print("-"*50)

#使用pop方法删除
df.pop('two')
print (df)

使用delpop都可以删除数据列,只不过两种使用方式有些不同,注意一下

这里建议使用pop,因为pop是DataFrame的方法,而其他添加/删除数据行/列操作都是靠DataFrame方法来完成的,所以这里也用pop方法,和其他形成统一,不容易用错

行索引操作DataFrame

标签索引选取

# 标签索引选取

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print(df)
print("-"*50)

# 选取单个数据 
print(df.loc[["a"],["one"]])
print("-"*50)

# 选取多个数据
print(df.loc["a":"c","one":"two"])
print("*-"*50)
print(df.loc[["a","d"],["one"]])

loc只接收标签索引,前面是行标签,后面是列标签,都是传列表(但是使用:时,不要传列表,直接使用即可)。选取多个数据的切片和Series差不多

整数索引选取

# 整数索引选取

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print(df)
print("-*-"*50)

# 选取单个数据
print (df.iloc[[1],[1]])
print("-"*50)

# 选取多个数据
print(df.iloc[1:3,0:1])
print("-"*50)
print(df.iloc[[0,2],[1]])

iloc只接收整数索引,前面表示行,后面表示列,都是从零开始计数的,都是传列表(但是使用:时,不要传列表,直接使用即可)。选取多个数据的切片和Series差不多

切片操作多行选取

# 切片选取多行

d = {'one' : pd.Series([1, 2, 3], index=['a', 'b', 'c']),
   'two' : pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print(df)
print("-"*50)

#左闭右开
print(df[2:4])

添加数据行

# 使用append添加数据行,添加到末尾(这个在pandas2.0之后被移除了)
# 使用concat拼接两个DataFrame

df = pd.DataFrame([[1, 2], [3, 4]], columns = ['a','b'])
df2 = pd.DataFrame([[5, 6], [7, 8]], columns = ['a','b'])
print(df)
print("-"*50)
print(df2)
print("-"*50)

#在行末追加新数据行
# df = df.append(df2)
df=pd.concat([df,df2])
print(df)

注意:在有些地方还使用append添加。然而在pandas2.0之后就被移除。我们可以使用concat来平替。

删除数据

# 使用drop方法删除行数据

df = pd.DataFrame([[1, 2], [3, 4]], columns = ['a','b'])
df2 = pd.DataFrame([[5, 6], [7, 8]], columns = ['a','b'])
df=pd.concat([df,df2])
print(df)
print("-"*50)

#注意此处调用了drop()方法
df = df.drop(0)
print (df)

常用属性和方法

DataFrameSeries差不多

名称

属性&方法

T

行和列转置。

axes

返回一个仅以行轴标签和列轴标签为成员的列表。

dtypes

返回每列数据的数据类型。

empty

DataFrame中没有数据或者任意坐标轴的长度为0,则返回True。

ndim

轴的数量,也指数组的维数。(都是2)

shape

返回一个元组,表示了 DataFrame 维度。

size

DataFrame中的元素数量。

values

使用 numpy 数组表示 DataFrame 中的元素值。

head()

返回前 n 行数据。

tail()

返回后 n 行数据。

shift()

将行或列移动指定的步幅长度

代码演示

# 创建

d = {'Name':pd.Series(['c语言中文网','编程帮',"百度",'360搜索','谷歌','微学苑','Bing搜索']),
   'years':pd.Series([5,6,15,28,3,19,23]),
   'Rating':pd.Series([4.23,3.24,3.98,2.56,3.20,4.6,3.8])}

# 构建DataFrame
df = pd.DataFrame(d)

# 输出DataFrame
print(df)
print("-"*50)

# 转置
print(df.T)
print("-"*50)

# axes
print(df.axes)
print("-"*50)

# dytpe
print(df.dtypes)
print("-"*50)

# empty
print(df.empty)
print("-"*50)

# ndim
print(df.ndim)
print('-'*50)

# shape
print(df.shape)
print("-"*50)

# size
print(df.size)
print("-"*50)

# values
print(df.values)
print("-"*50)

# head和tail
print(df.head(3))
print("-"*50)
print(df.tail(2))
print("-"*50)

# shift

info= pd.DataFrame({'a_data': [40, 28, 39, 32, 18], 
'b_data': [20, 37, 41, 35, 45], 
'c_data': [22, 17, 11, 25, 15]}) 

#移动幅度为3
info.shift(periods=3)
print(info)
print("-"*50)
info.shift(periods=3,axis=1,fill_value= 52)
print(info)

关于这个shift,我也没有搞明白,等啥时候我搞明白了再回来补吧

总结

具体参考C语言中文网

数据分析和可视化到这就告一段落,把这些知识大致过一遍就可以了

后面去学机器学习了

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐