美文网首页
pandas初阶使用

pandas初阶使用

作者: 风少侠 | 来源:发表于2018-12-13 10:56 被阅读11次

    pandas数据类型

    pandas 基于两种数据类型,series 和 dataframe。

    • series 是一种一维的数据类型,其中的每个元素都有各自的标签。标签可以是数字或者字符。
    • dataframe 是一个二维的、表格型的数据结构。pandas 的 dataframe 可以储存许多不同类型的数据,类似于我们常用的excel。dataframe 可以看成一个series的字典{"key1":series1,"key2":series2}。

    接入pandas

    pandas是python的一个第三方库,使用前需要先进行安装:

    pip3 install pandas

    安装完成后我们来导入这个库:

    import pandas as pd
    

    接下来我们新建一个数据集,并对它进行操作。我们可以选择新建一个数据集,或者从本地文件中导入,这里我们选择后者,因为这更符合我平时的使用场景。pandas提供了丰富的api来读取各种文件:


    pandas_read.png

    这里我们新建一个Excel,读取并打印:

    标题1 标题2 标题3 标题4
    1 11 111 1a
    2 22 222 2a
    3 33 333 3a
    4 44 444 4a
    5 55 555 5a
    df = pd.read_excel("C:/Users/Administrator/Desktop/新建 Microsoft Excel 工作表.xlsx")
    print(df)
    #   标题1  标题2  标题3 标题4
    #0    1   11  111  1a
    #1    2   22  222  2a
    #2    3   33  333  3a
    #3    4   44  444  4a
    #4    5   55  555  5a
    

    数据前面的0,1,2,3,4为行索引,从0开始。

    获取数据基本信息

    获取行数、列数

    print(df.shape)
    # (5, 4)
    

    我们得到一个tuple,tuple[0]为行,tuple[1]为列。并且我们可以得到一个信息,它会默认第一个非空行为题头,数据的行数并没有计算标题行。

    获取标题

    print(df.columns.values.tolist())
    # ['标题1', '标题2', '标题3', '标题4']
    

    如果某列没有标题头,会得到Unnamed x。

    获取数据数目

    print(len(df))
    # 5
    

    这里的数据指的一行为一条数据,所以返回的实际就是行数。

    数据的过滤

    获取前几行或者后几行

    print("前两行:\n")
    print(df.head(2))
    print("-----------")
    print("后两行:\n")
    print(df.tail(2))
    
    #前两行:
    #   标题1  标题2  标题3 标题4
    #0    1   11  111  1a
    #1    2   22  222  2a
    #-----------
    #后两行:
    #   标题1  标题2  标题3 标题4
    #3    4   44  444  4a
    #4    5   55  555  5a
    

    获取某列

    print(df["标题1"])
    #0    1
    #1    2
    #2    3
    #3    4
    #4    5
    
    
    # 将 标题1 这列切割出来,注意会再原数据集中删除
    # print(df.pop("标题1"))
    

    注意前面的第一列01234为它的索引。
    除了这种方式外,我们也可以使用小数点来调用:

    print(df.标题1)
    

    得到的结果是一样的,不过在程序里面用中文总觉得哪里怪怪的,我们可以自定义标题:

    df.columns = ["title_1", "title_2", "title_3", "title_4"]
    print(df.title_1)
    

    获取符合条件的数据

    比如我们需要获取第一列小于3的数据:

    print(df[df.title_1 < 3])
    #   title_1  title_2  title_3 title_4
    #0        1       11      111      1a
    #1        2       22      222      2a
    

    比如我们需要获取第一列小于3并且第二列小于20的数据:

    print(df[(df.title_1 < 3) & (df.title_2 < 20)]) 
    #   title_1  title_2  title_3 title_4
    #0        1       11      111      1a
    

    注意不能使用and、or,必须用 &、| 和圆括号。
    如果数据为字符串,我们也可以用字符串的方法来进行过滤,格式为.str.[string method]:

    print(df[df.title_4.str.startswith("2")])
    #   title_1  title_2  title_3 title_4
    #1        2       22      222      2a
    print(df[df.title_4.str.endswith("a")])
    #   title_1  title_2  title_3 title_4
    #0        1       11      111      1a
    #1        2       22      222      2a
    #2        3       33      333      3a
    #3        4       44      444      4a
    #4        5       55      555      5a
    

    数据的索引

    获取某条数据

    比如我想获取第4行数据:

    print(df.iloc[3])
    #title_1      4
    #title_2     44
    #title_3    444
    #title_4     4a
    #Name: 3, dtype: object
    

    注意索引是从0开始的。
    比如我想获取第4列值为3a的那一条数据,我们可以先设置第四列为索引:

    df = df.set_index(["title_4"])
    print(df.loc["3a"])
    #title_1      3
    #title_2     33
    #title_3    333
    #Name: 3a, dtype: int64
    

    此时我们打印一下数据集:

    print(df)
    #         title_1  title_2  title_3
    #title_4                           
    #1a             1       11      111
    #2a             2       22      222
    #3a             3       33      333
    #4a             4       44      444
    #5a             5       55      555
    

    刚好可以验证我们之前0,1,2,3,4是索引的说法。
    如果我们使用完毕,可以用以下方法来将索引恢复成数据形式:

    df = df.reset_index(["title_4"]) 
    print(df)
    #  title_4  title_1  title_2  title_3
    #0      1a        1       11      111
    #1      2a        2       22      222
    #2      3a        3       33      333
    #3      4a        4       44      444
    #4      5a        5       55      555
    

    数据排序

    我们将数据按降序排列:

    df.sort_index(ascending=False, inplace=True)
    print(df)
    #  title_4  title_1  title_2  title_3
    #4      5a        5       55      555
    #3      4a        4       44      444
    #2      3a        3       33      333
    #1      2a        2       22      222
    #0      1a        1       11      111
    

    ascending:True为升序,False为降序。 inplace:是否替换原数据,默认False。
    注意它的索引一起跟着倒序了,这时候我们调用df.iloc[1]得到的依然是2a那行数据。

    数据的修改

    删除行、列

    我们可以使用drop方法来删除行或者列:

    # 删除title_1列
    result_2 = df.drop(labels=["title_1"], axis=1, inplace=False)
    print(result_2)
    #  title_4  title_2  title_3
    #4      5a       55      555
    #3      4a       44      444
    #2      3a       33      333
    #1      2a       22      222
    #0      1a       11      111
    
    # 删除前两列
    result_2 = df.drop(labels=df.columns[[0, 1]], axis=1, inplace=False)
    print(result_2)
    #   title_2  title_3
    #4       55      555
    #3       44      444
    #2       33      333
    #1       22      222
    #0       11      111
    
    # 删除前两行
    result_2 = df.drop(labels=[0, 1], axis=0, inplace=False)
    print(result_2)
    #  title_4  title_1  title_2  title_3
    #4      5a        5       55      555
    #3      4a        4       44      444
    #2      3a        3       33      333
    

    参数labels表示要删除的标签;axis为0表示行,1表示列,默认0;inplace表示是否要替换原数据集。

    插入行、列

    # 再最后添加一列
    #df["title_5"] = ["1","2","3","4","5"]
    
    # 插入到第一列
    #data = ["1","2","3","4","5"]
    #df2.insert(0,'title_5',data)
    
    # 插入行,先切割两部分再拼接,可以使用append或者concat
    #df_1.append(insertRow,ignore_index=True).append(df_2,ignore_index=True)
    # 或者
    #pd.concat([df_1,insertRow,df_2],ignore_index=True)
    

    修改具体数据值

    apply

    当我们想让操作作用在一维的向量上时,可以使用apply。它可以作用于Series,也可以作用于DataFrame数据。

    # 作用于某一列,Series数据。
    df["title_5"] = df.title_4.apply(self.apply_data)   # 新增一列
    print(df)
    
    def apply_data(self, data):
        result = data[:1]
        return result + "b"
    
    #  title_4  title_1  title_2  title_3 title_5
    #4      5a        5       55      555      5b
    #3      4a        4       44      444      4b
    #2      3a        3       33      333      3b
    #1      2a        2       22      222      2b
    #0      1a        1       11      111      1b
    
    
    # 作用于DataFrame 数据
    result_2 = df.apply(self.apply_data_2)    # 获取第二行数据
    print(result_2)
    
    def apply_data_2(self, data):
       return data[1]
    
    #title_4     2a
    #title_1      2
    #title_2     22
    #title_3    222
    #title_5     2b
    #dtype: object
    

    applymap

    如果想让操作作用于DataFrame中的每一个元素,可以使用applymap():

    df = df.applymap(self.applymap_data)
    print(df)
    
    def applymap_data(self, data):
        return str(data) + "c"
    
    #  title_4 title_1 title_2 title_3 title_5
    #4     5ac      5c     55c    555c     5bc
    #3     4ac      4c     44c    444c     4bc
    #2     3ac      3c     33c    333c     3bc
    #1     2ac      2c     22c    222c     2bc
    #0     1ac      1c     11c    111c     1bc
    

    map

    map()只能是将函数作用于一个Series的每一个元素:

    print(df.title_1.map(self.apply_data))
    
    #4    5b
    #3    4b
    #2    3b
    #1    2b
    #0    1b
    #Name: title_1, dtype: object
    

    总的来说就是apply()是一种让函数作用于列或者行操作,applymap()是一种让函数作用于DataFrame每一个元素的操作,而map是一种让函数作用于Series每一个元素的操作。

    数据分组

    为了方便演示我们先添加一列数据,然后通过groupby进行分组:

    df["title_6"] = ["1", "0", "1", "0", "1"]
    print(df.groupby(df.title_6).max())  # 获取每个分组里面最大的数据
    
    #        title_4 title_1 title_2 title_3 title_5 title_6
    #title_6                                                
    #0           4ac      4c     44c    444c     4bc       0
    #1           5ac      5c     55c    555c     5bc       1
    
    print(df.groupby(df.title_6).max()["title_1"])  # 获取分组后的某列
     print(df.groupby([df.title_6, df.title_5]).max())
    #title_6
    #0    4c
    #1    5c
    #Name: title_1, dtype: object
    

    类似的还有min(),mean()等方法。
    我们也可以根据多个列进行分组:

    df = df.groupby([df.title_6, df.title_5]).max()
    print(df)
    #                title_4 title_1 title_2 title_3 title_5 title_6
    #title_6 title_5                                                
    #0       2bc         2ac      2c     22c    222c     2bc       0
    #        4bc         4ac      4c     44c    444c     4bc       0
    #1       1bc         1ac      1c     11c    111c     1bc       1
    #        3bc         3ac      3c     33c    333c     3bc       1
    #        5bc         5ac      5c     55c    555c     5bc       1
    

    我们也可以通过unstack方法来改变分组后的显示形式:

    print(df.unstack(0))
    #        title_4      title_1      title_2 ...  title_3 title_5      title_6     
    #title_6       0    1       0    1       0 ...        1       0    1       0    1
    #title_5                                   ...                                   
    #1bc         NaN  1ac     NaN   1c     NaN ...     111c     NaN  1bc     NaN    1
    #2bc         2ac  NaN      2c  NaN     22c ...      NaN     2bc  NaN       0  NaN
    #3bc         NaN  3ac     NaN   3c     NaN ...     333c     NaN  3bc     NaN    1
    #4bc         4ac  NaN      4c  NaN     44c ...      NaN     4bc  NaN       0  NaN
    #5bc         NaN  5ac     NaN   5c     NaN ...     555c     NaN  5bc     NaN    1
    
    #[5 rows x 12 columns]
    
    print(df.unstack(1))
    #        title_4                     ...  title_6                    
    #title_5     1bc  2bc  3bc  4bc  5bc ...      1bc  2bc  3bc  4bc  5bc
    #title_6                             ...                             
    #0           NaN  2ac  NaN  4ac  NaN ...      NaN    0  NaN    0  NaN
    #1           1ac  NaN  3ac  NaN  5ac ...        1  NaN    1  NaN    1
    
    #[2 rows x 30 columns]
    

    传入的参数0、1表示将第几个索引置为横向。
    其中很多的NaN表示空记录,比如第一条记录对应title_5 = 1bc & title_6 = 0,实际数据集中没有这样的数据,因此显示NaN,如果觉得看起来不直观,也可以使用fillna方法来替换调NaN的显示:

    print(df.unstack(0).fillna(""))
    
    #        title_4      title_1     title_2 ... title_3 title_5      title_6   
    #title_6       0    1       0   1       0 ...       1       0    1       0  1
    #title_5                                  ...                                
    #1bc              1ac          1c         ...    111c          1bc          1
    #2bc         2ac           2c         22c ...             2bc            0   
    #3bc              3ac          3c         ...    333c          3bc          1
    #4bc         4ac           4c         44c ...             4bc            0   
    #5bc              5ac          5c         ...    555c          5bc          1
    
    #[5 rows x 12 columns]
    

    fillna传入的参数表示你想要替换的显示值,这里传入空字符串,当然你也可以传入任意的字符串或者数字。

    上面的一系列操作也可以用pivot方法来代替:

    print(df)
    #  title_4 title_1 title_2 title_3 title_5 title_6
    #4     5ac      5c     55c    555c     5bc       1
    #3     4ac      4c     44c    444c     4bc       0
    #2     3ac      3c     33c    333c     3bc       1
    #1     2ac      2c     22c    222c     2bc       0
    #0     1ac      1c     11c    111c     1bc       1
    
    print(df.pivot(index="title_6", columns="title_5", values=["title_1", "title_2"]).fillna(""))
    #        title_1                 title_2                    
    #title_5     1bc 2bc 3bc 4bc 5bc     1bc  2bc  3bc  4bc  5bc
    #title_6                                                    
    #0                2c      4c              22c       44c     
    #1            1c      3c      5c     11c       33c       55c
    

    参数index代表索引列,columns代表横向的那个分组,values表示要显示的值。上面的写法也可以写成:

    # 获取所有数据再单独显示某几列
    print(df.pivot("title_6", "title_5")[["title_1", "title_2"]].fillna(""))
    

    数据合并

    如果有两个相关联的数据集,比如两个数据集有相同的某列,可以用merge方法合并成一个数据集。

    # 以title_1为根据将两个数据集合并
    df.merge(df_other, on='title_1')
    

    数据的保存

    还是以Excel为例,我们将数据读取进来,进行一系列操作后,很多时候会希望保存下来,我们可以直接使用to_excel方法,注意需要安装openpyxl库:

    df.to_excel("data_new.xlsx")
    
    to_excel.png

    相关文章

      网友评论

          本文标题:pandas初阶使用

          本文链接:https://www.haomeiwen.com/subject/kcfphqtx.html