#!/usr/bin/env python # coding: utf-8 # # 二维数据结构DataFrame对象 # DataFrame对象是一种二维带标记数据结构,不同列的数据类型可以不同。为了方便理解,可以将DataFrame对象看成一张Excel电子表格,或者是一个由多列Series对象构成的字典。 # In[1]: import numpy as np # In[2]: import pandas as pd # ## DataFrame对象的生成 # # 与Series类似,DataFrame对象也可以由多种类型的数据生成: # - 由Series对象为值构成的字典。 # - 由一维数组或列表构成的字典。 # - 由字典构成的列表或数组。 # ### 使用Series对象构成的字典生成 # DataFrame对象可以从一组由Series对象为值构成的字典中生成。字典中的值除了Series对象,也可以是另一个字典,因为字典被转换为Series对象。 # # 假设有一个包含两个Series对象的字典d: # In[3]: s1 = pd.Series([1, 2, 3], index=['a', 'b', 'c']) # In[4]: s2 = pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd']) # In[5]: d = {"one": s1, "two": s2} # 可以用字典d构造一个DataFrame对象: # In[6]: df = pd.DataFrame(d) # In[7]: df # 与Series相比,DataFrame对象要区分不同的行和列,因此有行标记和列标记之分。默认情况下,df的列标记是传入字典的键,可以用属性`.columns`查看: # In[8]: df.columns # 行标记是两个Series对象标记的并集,Pandas会自动将两个Series对象的标记进行对齐: # In[9]: df.index # 在生成DataFrame时,也可以指定index和columns参数: # In[10]: pd.DataFrame(d, index=["d", "b", "a"]) # Pandas会按照给定的顺序从传入的数据中寻找对应的值,如果该值不存在,则使用缺省值`np.nan`: # In[11]: pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three']) # ### 使用一维数组构成的字典生成 # DataFrame对象还可以使用由一维数组或列表构成的字典生成,这些数组和列表必须是等长的: # In[12]: d = {'one' : [1., 2., 3., 4.], 'two' : [4., 3., 2., 1.]} # In[13]: pd.DataFrame(d) # 传入index参数时,该参数的长度也必须与列表长度一致: # In[14]: pd.DataFrame(d, index=['a', 'b', 'c', 'd']) # ### 使用字典数组生成 # 还可以使用字典构成的数组或列表进行构建: # In[15]: data = [{'a': 1, 'b': 2}, {'a': 5, 'b': 10, 'c': 20}] # In[16]: pd.DataFrame(data) # 与Series不同的是,字典的键对应的是列标记,行标记由数组或列表的大小决定。 # ### 使用二维数组生成 # 还可以使用NumPy的二维数组生成: # In[17]: a = np.array([[1,2,3], [4,5,6]]) # In[18]: pd.DataFrame(a) # ## DataFrame对象的使用 # # DataFrame对象不是二维NumPy数组,在使用方法上存在很大差异: # In[19]: s1 = pd.Series([1, 2, 3], index=['a', 'b', 'c']) # In[20]: s2 = pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd']) # In[21]: d = {"one": s1, "two": s2} # In[22]: df = pd.DataFrame(d) # In[23]: df # ### 列相关的操作 # DataFrame对象可以看成是一个由Series对象构成的字典,.columns属性对应字典的键,每一列对应字典的值: # In[24]: df['one'] # 可以像字典一样增加新列: # In[25]: df["three"] = df["one"] * df["two"] # In[26]: df["flag"] = df["one"] > 2 # In[27]: df # 增加新列时,如果新列的值是单一值,Pandas会按照行标记自动进行扩展: # In[28]: df["four"] = 4 # DataFrame对象支持用del关键字或者.pop()方法删除列: # In[29]: del df["two"] # In[30]: three = df.pop("three") # In[31]: three # In[32]: df # 增加一个行标记不完全相同的新列时,Pandas只会保留该列中与原有行标记相同的部分,以保证原DataFrame对象的行标记不变化: # In[33]: df["foo"] = pd.Series([1,2,3], index=["a", "d", "e"]) # In[34]: df # 默认情况下,新列的插入位置都在DataFrame对象的最后。可以使用.insert()方法将其插入指定的位置: # In[35]: df.insert(1, "bar", df["one"]) # In[36]: df # ### 行相关的操作 # # DataFrame对象有两种常用的索引行的方式。可以用`.loc`属性索引行标记,返回一个Series对象: # In[37]: df.loc["b"] # 也可以用.iloc属性索引位置,得到第二行数据: # In[38]: df.iloc[1] # ### 加法与减法操作 # # DataFrame对象支持加法和减法的操作,并且按照行列标记对齐的原则进行计算: # In[39]: df1 = pd.DataFrame(np.random.randn(10, 4), columns=['A', 'B', 'C', 'D']) # In[40]: df2 = pd.DataFrame(np.random.randn(7, 3), columns=['A', 'B', 'C']) # In[41]: df1 + df2 # DataFrame对象还可以与Series对象进行加减操作。与NumPy中的广播机制类似,Pandas会先将Series对象的标记与DataFrame对象的列标记中对应的部分拿出来,然后使用广播机制将Series对象沿着行标记进行扩展: # In[42]: df1 # In[43]: df1 - df1.iloc[0] # In[ ]: