相关文章推荐
欢乐的柳树  ·  Python ...·  1 年前    · 
长情的消防车  ·  kube-apiserver pod ...·  2 年前    · 
温暖的饭卡  ·  shell if语句 -eq-掘金·  2 年前    · 

DataFrame


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

最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一【列】的名称,以字典的值(一个数组)作为每一列。
此外,DataFrame会自动加上每一行的索引(和Series一样)。
同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。
# 字典创建
df1 = DataFrame({"Python":[99,98,89,97,88],
               "Java":[56,75,46,86,39],
               "C++":[98,54,76,45,84]},
               index = list("abcde"),
              columns = ["Python","Java","C++","PHP"])
# index(列索引不能多也不能少)
# columns(行索引可多可少:多的为NaN,少的不显示)
DataFrame属性:values、columns、index、shape
df1.values   -- 打印value值
df1.columns  -- 打印列索引
df1.shape    -- 打印形状
df1.index    -- 打印行索引
# ndarray对象创建
df2 = DataFrame(data=np.random.randint(0,100,size=(5,4)),
              index = list("abcde"),
              columns = ["Python","Java","Html","PHP"])
2、DataFrame的索引
1对列进行索引
1. 通过类似字典的方式
2. 通过属性的方式
可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。
df2.Python
df2["Python"]  -- 这个方法比较常用(列表中可以传多个值,用逗号隔开)
# 列不支持切片操作
2对行进行索引
1. 使用.loc[]加index来进行行索引
2. 使用.iloc[]加整数来进行行索引
同样返回一个Series,index为原来的columns。
# 行索引不支持直接使用中括号(即df2[]是错误的写法)
df2.loc["a"] df2.iloc[0] -- 这两种方法(使用一个中括号)得到的是Series对象
df2.loc[["a"]] df2.iloc[[0]] -- 使用两个中括号得到的是DataFrame对象
 -- 可以传多个值,用逗号隔开
df2.loc["a":"c"] -- 闭区间(左闭右闭)
df2.iloc[0:3] -- 左开右闭区间
3对元素索引的方法
1. 使用列索引
2. 使用行索引(iloc[3,1]相当于两个参数;iloc[[3,3]] 里面的[3,3]看做一个参数)
3. 使用values属性(二维numpy数组)
df2["Python"]["c"]     -- 先列索引,后行索引
df2.loc["c"]["Python"] -- 先行索引,后列索引
# 【注意】 直接用中括号时:
   索引表示的是列索引
   切片表示的是行切片
3、DataFrame的运算

1DataFrame之间的运算
同Series一样:
在运算中自动对齐不同索引的数据
如果索引不对应,则补NaN
   df1+df2 df1.add(df2, fill_value=0)
Html Java Python Ruby 数学 英语 语文 Html Java Python Ruby 数学 英语 语文
a NaN NaN 131 NaN NaN NaN NaN     a 121.0 132.0 131 125.0 120.0 NaN 123.0
b NaN NaN 235 NaN NaN NaN NaN      b 1.0 123.0 235 48.0 136.0 NaN 114.0
c NaN NaN 228 NaN NaN NaN NaN      c 130.0 77.0 228 29.0 141.0 NaN 130.0
d NaN NaN 130 NaN NaN NaN NaN      d 18.0 88.0 130 33.0 129.0 NaN 117.0
 
2Series与DataFrame之间的运算
使用Python操作符:以行为单位操作(参数必须是行),对所有行都有效。(类似于numpy中二维数组与一维数组的运算,但可能出现NaN)
使用pandas操作函数:
axis=0:以列为单位操作(参数必须是列),对所有列都有效。
axis=1:以行为单位操作(参数必须是行),对所有行都有效。
df2  ----> DataFrame对象
s_row = df2.loc["c"] ---- Series对象
s_column = df2["Python"] ---- Series对象
df2.add(s_row) ---- df2对象每一列与s_row相加
df2.add(s_column, axis="index") ---- df2对象每一行与s_column相加
# axis参数,指定两者相加的方式,默认等于column

丢失数据的处理

分为两种: None np.nan(NaN)


numpy中:
   type(None) ---- NoneType
   None是Python自带的,其类型为python object。因此,### None不能参与到任何计算中。
   object类型的运算要比int类型的运算慢得多
   计算不同数据类型求和时间
   %timeit np.arange(1e5,dtype=xxx).sum()

   %timeit np.arange(1e6, dtype = int).sum()
   3.21 ms ± 1.01 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
   %timeit np.arange(1e6, dtype = float).sum()
   6.89 ms ± 1.3 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
   %timeit np.arange(1e6, dtype = object).sum()
   89.3 ms ± 9.79 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
pands中:
pandas中将None视作np.nan
np.nan(NaN)

numpy中:
   np.nan是浮点类型,能参与到计算中。但计算的结果总是NaN。
   但可以使用np.nan*()函数来计算nan,此时视nan为0
   nd = np.array([10,20,30,np.nan])
   np.nansum(nd) ----> 60.0    # 将nan视为0
pandas中:
pandas中None与np.nan都视作np.nan
df = DataFrame([10,20,57,np.nan, None],index = list("abcde"), columns = ["Python"])
   df.sum() ----> 87.0
   df = DataFrame([[10,20,57,np.nan,None],
              [22,33,56,12,None],
              [np.nan,1,2,3,4]], index = list("abc"),
             columns = ["Python","Java","数学","物理","H5"])
   df.sum(axis=1) ----> 求每一行的和
pandas中None与np.nan操作

判断函数:
isnull():数据是否为空
notnull():数据是否不为空
#DataFrame的isnull函数返回的是和之前一模一样的结构,且为boolean类型,不为空的False 为空的True
isnull().any() -- 判断行或列中的数据是否有空值,有返回True,没有返回False
notnull().all() -- 判断行或列的数据是否全不为空,是返回True,否则返回False
用法:
df = DataFrame([[10,20,57,np.nan,None],
              [22,33,56,12,None],
              [np.nan,1,2,3,4]], index = list("abc"),
             columns = ["Python","Java","数学","物理","H5"])
   df2 = DataFrame([[10,20,57,90,20],
              [22,33,56,12,80],
              [100,1,2,3,4]], index = list("efg"),
             columns = ["Python","Java","数学","物理","H5"])
   df3 = df.add(df2, fill_value=0) ---- df+df2
   df3_isnull = df3.isnull().any(axis = 1) ---- 判断df3每行是否有空值,返回Series类型
   df3[df3_isnull] ---- 把非空值的行过滤掉,留下含空值的行
扩展:
cond = (df3 >= 10).all(axis = 1)
   # 判断df3每一行数据是否全部都大于等于10,返回series类型对象,且值为布尔类型
   df3[cond] ---- 取出df3中值全部大于等于10的数据
过滤函数:
   dropna(): 过滤丢失数据
   df3["H5"] = np.nan  ---- DataFrame的列索引,把“H5”列全部赋值为np.nan
   df3.dropna(axis = 1, how = "all") ---- 过滤掉值全为空的列
  axis :可以选择过滤的是行还是列(默认为行,axis=0
  也可以选择过滤的方式 how = 'all'
填充函数:
   fillna(): 填充丢失数据
df3.fillna(-1) ---- 将df3中为空的数据全部填充为-1
   df3.fillna(method="bfill") ---- 向后填充(用下一行的数据填充)
   df3.fillna(method="ffill") ---- 向前填充(用上一行的数据填充)
   df3.fillna(method="ffill",axis = 1) ---- 向右进行填充(用左边的数据填充)
   df3.fillna(method="bfill",axis = 1) ---- 向左进行填充(用右边的数据填充)
   # method:可以选择前向填充还是后向填充
   # 对于DataFrame来说,还要选择填充的轴axis;axis=0:index/行;axis=1:columns/列

pandas层次化索引

创建多层行索引

1隐式构造
最常见的方法是给DataFrame构造函数的index参数传递两个或更多的数组
Series也可以创建多层索引
s = Series(data = [1,2,3,"a"],
         index = [["a","a","b","b"],["期中","期末","期中","期末"]])
DataFrame:
# 二层索引
df = DataFrame(data = [1,2,3,"a"],
              index = [["a","a","b","b"],["期中","期末","期中","期末"]],
             columns = ["Python"])
   # 三层索引
   df = DataFrame(data = np.random.randint(0,150,size = 8),
             index = [['a',"a","a","a","b","b","b","b"],
                      ['期中',"期中","期末","期末",'期中',"期中","期末","期末"],
                      ["一单元","二单元","一单元","二单元","一单元","二单元","一单元","二单元"]],
             columns = ["Python"])
2显示构造 pd.MultiIndex
   1. 使用数组
   df1 = DataFrame(data = np.random.randint(0,150,size = (8,4)),
              index = pd.MultiIndex.from_arrays([['a',"a","a","a","b","b","b","b"],
                      ['期中',"期中","期末","期末",'期中',"期中","期末","期末"],
                      ["一单元","二单元","一单元","二单元","一单元","二单元","一单元","二单元"]]),
              columns = ["Python","h5","php","go"])
   2. 使用tuple
   df3 = DataFrame(np.random.randint(0,150,size = 4),
               index = pd.MultiIndex.from_tuples([("a",1),("a",2),("b",1),("b",2)]),
              columns = ["Python"])
   3. 使用product  ---- 最简单,推荐使用
   df4 = DataFrame(np.random.randint(0,150,size = (8,2)),
               index = pd.MultiIndex.from_product([list("abcd"), ["期中","期末"]]),
              columns = ['Python',"数学"])
多层列索引

除了行索引index,列索引columns也能用同样的方法创建多层索引
df = DataFrame(data = np.random.randint(0,150,size = (1,8)),
             columns = [['a',"a","a","a","b","b","b","b"],
                      ['期中',"期中","期末","期末",'期中',"期中","期末","期末"],
                      ["一单元","二单元","一单元","二单元","一单元","二单元","一单元","二单元"]],
             index = ["Python"])
多层索引对象的索引与切片操作

1Series的操作
# 对于Series来说,直接中括号[]与使用.loc()完全一样,因此,推荐使用中括号索引和切片。
s = Series(data=[1,2,3,"a"], index = [["a","a","b","b"],["期中","期末","期中","期末"]])
1. 索引
   s["a"]["期末"] s["a","期末"] ---- 效果相同
   2. 切片
   s["a":"b"] ---- 得到整个对象
   s["期中":"期末"] ---- 空的对象  
   # 这两种方法得到的对象不精确,不推荐使用
   s.iloc[0:3] ---- 隐式索引切片
   # 把所有的数据放到一块进行切片,得到的数据比较精确 推荐使用
2DataFrame的操作
(1) 可以直接使用列名称来进行列索引
(2) 使用行索引需要用ix(),loc()等函数
【极其重要】推荐使用loc()函数
# 注意: 在对行索引的时候,若一级行索引还有多个,对二级行索引会遇到问题!也就是说,无法直接对二级索引进行索引,必须让二级索引变成一级索引后才能对其进行索引!
df4 = DataFrame(np.random.randint(0,150,size = (8,2)),
               index = pd.MultiIndex.from_product([list("abcd"), ["期中","期末"]]),
              columns = ['Python',"数学"])
df4["Python"]["a","期末"] ---- 先列索引,再行索引
df4.loc["a"].loc["期末"]["Python"] ---- 先行索引,再列索引
# 在索引取值的时候,一定要注意数据的类型

unstack():行索引变列索引
df4.unstack() ---- 把第二层的行索引变成列索引
df4.unstack(level=1) ---- 把第二层的行索引变成列索引
df1.unstack(level = 1) ---- 把df1的第二层行索引变为列索引
# 【小技巧】使用unstack()的时候,level等于哪一个,哪一个就消失,出现在列里。
stack(): 列索引变行索引
df.stack(level=1) ---- 把df的第二层列索引变成行索引
df.stack(level=(0,2)) ---- 把df的第一层、第三层列索引放到行索引上面
# 【小技巧】使用stack()的时候,level等于哪一个,哪一个就消失,出现在行里。
# level索引的下标(从0开始计数)最外层为0,第二层为1,以此类推

【注意】需要指定axis
【小技巧】和unstack()相反,聚合的时候,axis等于哪一个,哪一个就保留。
所谓的聚合操作:平均数,方差,最大值,最小值……
df4.div(10, axis = "index") ---- df4的数据除10
df4.sum(axis = 1) ---- 按行求和
df4.std() ---- df4的标准差

pandas的拼接操作


pandas的拼接分为两种:
级联:pd.concat, pd.append
合并:pd.merge, pd.join
使用pd.concat()级联