2、DataFrame

DataFrame是一个【表格型】的数据结构,可以看做是【由Series组成的字典】(共用同一个索引)。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。

  • 行索引:index
  • 列索引:columns
  • 值:values(numpy的二维数组)

我们的 训练集(一些二维的数据)都是二维的,那么Series满足不了这个条件,xy轴,轴上的一点(0,0)

1)DataFrame的创建

最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一【列】的名称,以字典的值(一个数组)作为每一列。

此外,DataFrame会自动加上每一行的索引(和Series一样)。

同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。

data = pd.DataFrame(data=np.random.randint(1,20,(5,4))
             ,index=['红浪漫','海螺哥','澡王','大哥','三点哥']
             ,columns=list('ABCD'))

DataFrame属性:values、columns、index、shape、ndim、dtypes

data.ndim,data.shape
#(2, (5, 4))
data.dtypes
#A int32
#B int32
#C int32
#D int32
#dtype: object
#行索引
data.index
#Index(['红浪漫', '海螺哥', '澡王', '大哥', '三点哥'], dtype='object')
#列索引
data.columns
#Index(['A', 'B', 'C', 'D'], dtype='object')
data.values
#array([[12, 15, 17, 8],
# [10, 14, 4, 2],
# [12, 19, 13, 6],
# [16, 12, 5, 8],
# [18, 14, 3, 16]])
#检查数据大小
data.info()
#<class 'pandas.core.frame.DataFrame'>
#Index: 5 entries, 红浪漫 to 三点哥
#Data columns (total 4 columns):
#A 5 non-null int32
#B 5 non-null int32
#C 5 non-null int32
#D 5 non-null int32
#dtypes: int32(4)
#memory usage: 280.0+ bytes

2)DataFrame的索引

(1) 对列进行索引

  • 通过类似字典的方式
  • 通过属性的方式
    可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。
data

data['A']
#红浪漫 12
#海螺哥 10
#澡王 12
#大哥 16
#三点哥 18
#Name: A, dtype: int32
data.A
#红浪漫 12
#海螺哥 10
#澡王 12
#大哥 16
#三点哥 18
#Name: A, dtype: int32

错误演示,取行的索引

DataFrame的中括号,只能获取列索引。

data['红浪漫']

(2) 对行进行索引

  • 使用.loc[]加index来进行行索引
  • 使用.iloc[]加整数来进行行索引
    同样返回一个Series,index为原来的columns。
#显式索引的主要作用式获取值的
data

data.loc['澡王'].B
#19
data.T.红浪漫.B
#15

(3) 对元素索引的方法

  • 使用列索引
  • 使用行索引(iloc[3,1]相当于两个参数;iloc[[3,3]] 里面的[3,3]看做一个参数)
  • 使用values属性(二维numpy数组)
#隐式索引的主要作用式切片
data.iloc[0,0]
#12

使用行索loc引切片

data.index
#Index(['红浪漫', '海螺哥', '澡王', '大哥', '三点哥'], dtype='object')
data.loc['红浪漫':'三点哥','B':]

使用隐式iloc

data.iloc[0:-1]

3)DataFrame的运算

(1) DataFrame之间的运算

同Series一样:

在运算中自动对齐不同索引的数据
如果索引不对应,则补NaN

df1 = pd.DataFrame(data=np.ones(shape=(5,4)),columns=list('abcd'),index=list(range(5)))
df2 = pd.DataFrame(data=np.zeros(shape=(5,4)),columns=list('bcde'),index=list(range(1,6)))
#如果有不存在的列,那么漠然该列的值位NaN
df3 = df1+df2
df3

#ndarray中运算只要考虑矩阵问题
#在df中我们还要索引是否整齐
df3.sum()
df1.values + df2.values
#array([[1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.],
# [1., 1., 1., 1.]])

下面是Python 操作符与pandas操作函数的对应表:

(2) Series与DataFrame之间的运算

【重要】

使用Python操作符:以行为单位操作(参数必须是行),对所有行都有效。(类似于numpy中二维数组与一维数组的运算,但可能出现NaN)

使用pandas操作函数:

axis=0:以列为单位操作(参数必须是列),对所有列都有效。
axis=1:以行为单位操作(参数必须是行),对所有行都有效。

列方向

df1

s1 = pd.Series(data=np.full(shape=4,fill_value=2),index=list('bcde'))
s1
#b 2
#c 2
#d 2
#e 2
#dtype: int32
df1+s1

DataFrame的CURD操作

user = pd.DataFrame(np.random.randint(0,100,(5,4)),index=list('东南西北中'),
                    columns=['username','sex','addr','seet'])
user

插入
#增加一行
user.loc['东邪'] = ['李晶','?','红浪漫',1123]
user

#增加一列 一列中有多少哥元素是不知道的
user.loc[:,'age'] = np.nan
user

##### 修改
import warnings
warnings.filterwarnings('ignore')
#查询到你想要修改的数据
#查询 username = 李晶
cond_index = user.username == '李晶'
cond_index
#东 False
#南 False
#西 False
#北 False
#中 False
#东邪 True
#Name: username, dtype: bool
#被拷贝的新数据,在单独的内存空间中
the_one = user.loc[cond_index]
the_one

the_one.age = 40
#把修改好的数据覆盖
user.loc[cond_index] = the_one
user

换一种方法
#query查询
new_data = user.query("username=='李晶'")
new_data.age = 50
user.loc[new_data.index] = new_data
user

查询
第一种方式
#查询username = 李晶 and addr=红浪漫
cond1 = user.username == '李晶'
cond2 = user.loc[cond1].addr == '红浪漫'
user.loc[cond1].loc[cond2]

#查询username = 李晶 or addr=红浪漫
cond3 = user.username == '李晶'
cond4 = user.addr == 84
#在一个df中追加一条数据
user.loc[cond3].append(user.loc[cond4])

第二种方法
user.query("username=='李晶' & addr=='红浪漫'")

user.query("username=='李晶' | addr==84")

删除

labels参数代表要被删除的索引名称
axis=0参数代表是删除行还是列
inplace 发生变化的数据把原数据替换

#删除列
user.drop(labels='age',axis=1,inplace=True)
#删除行
user.drop(labels='东邪',axis=0,inplace=True)
user