Advertisement

Coursera-Applied Data Science with Python-Introduction to Data Science in Python-Week2

阅读量:

一、The Series Data Structure:

可被视为pandas核心功能之一的数据架构,在其框架内可被视为一种一维数组类别的数据对象。其本质上类似于list和dictionary之间的折衷方案,在这种复合特性下整合了多维数组数据以及与其相关的索引信息。为了便于理解其功能机制,则可用有序字典这一概念来类比描述其特性;其中其索引系统采用连续递增的方式,默认起始为0

在底层实现中,pandas基于Numpy库将Series中的数值以类型数组的形式进行存储(即每个元素都有固定的数据类型)。这里使用的是Python中的列表结构(list)作为基础,并显著提高了处理效率。

1.创建Series:

以list创建Series:

当仅提供列表而不指定索引时,默认情况下pandas会对数据字段自动生成从零开始递增的索引编号。当未设置Series对象名称时,默认会根据处理内容附加相应的名称字段,并据此推断并附加相应的名称字段。例如,在以下两个案例中可以看到具体表现:第一个案例中的名称字段是object类型;第二个案例中的名称字段是int64类型。

复制代码
 import pandas as pd

    
 animals = ['Tiger', 'Bear', 'Moose']
    
 pd.Series(animals)
复制代码
 numbers = [1, 2, 3]

    
 pd.Series(numbers)

Python中使用None来表示数据缺失,在Pandas中根据所处理的数据对象类型不同而将缺失值分为两种形式:NoneNaN。其中一种形式(称为None)用于表示对象、字符串等类型的缺失数据;另一种形式(称为NaN)则用于表示数值型数据的丢失。这种分类方式的原因在于因为数值型数据丢失的信息较少且其存储效率较高。

复制代码
 animals = ['Tiger', 'Bear', None]

    
 pd.Series(animals)
复制代码
 numbers = [1, 2, None]

    
 pd.Series(numbers)

对于None和NaN来说,要注意下面几点:

以dictionary创建series:

复制代码
 sports = {'Archery': 'Bhutan',

    
       'Golf': 'Scotland',
    
       'Sumo': 'Japan',
    
       'Taekwondo': 'South Korea'}
    
 s = pd.Series(sports)
    
 s

可以通过Series的index属性获得所有的index

当我们使用字典创建Series对象时

指定index和value:

复制代码
 s = pd.Series(['Tiger', 'Bear', 'Moose'], index=['India', 'America', 'Canada'])

    
 s

指定的index和dictionary的key不匹配:

复制代码
 sports = {'Archery': 'Bhutan',

    
       'Golf': 'Scotland',
    
       'Sumo': 'Japan',
    
       'Taekwondo': 'South Korea'}
    
 s = pd.Series(sports, index=['Golf', 'Sumo', 'Hockey'])
    
 s

2.获得Series中的值:

在Series中(values可通过其索引的位置或标签进行查询)当未对series设置索引时 这些值实际上均是从零开始递增的整数

如果基于位置来进行数据访问时,则应调用pandas库中的iloc属性;而当数据表中的行基于列标签进行定位时,则应调用pandas库中的loc属性。举个简化的例子来说明问题会更加清晰。

复制代码
 sports = {'Archery': 'Bhutan',

    
       'Golf': 'Scotland',
    
       'Sumo': 'Japan',
    
       'Taekwondo': 'South Korea'}
    
 s = pd.Series(sports)
    
 s.iloc[3]
    
 s.loc['Golf']

在这个例子中,在Python中使用s.iloc[3]时会得到对应行号为3时的数据值(即South Korea);而使用s.loc['Golf']时会根据标记为'Golf'的数据项来获取其数据值(即Scotland)。

此外还具有一个功能能够实现该标签对应的值并且当该标签不存在时就会将其加入到series中

另外一种方式是采用直接使用方括号(即[""])的办法来进行查询。pandas会被方括号中的值的数据类型用来确定是调用iloc函数还是loc函数。在执行按行查询操作时,建议避免采取这种方式。这样做不仅会使代码的功能描述不够明确,并且可能导致程序运行时出现错误。

简述如下:当需要对数据框中的行进行检索时,默认情况下我们通常会采用loc和iloc属性来进行数据提取;而在涉及列访问的情况下,则常通过方括号('[]')来执行列访问操作。

该Series同样支持逐个遍历其元素;然而,在对Series的元素执行操作时,则应当优先采用运行效率较高的矢量化操作而非逐个元素处理的方法。为了比较矢量化与非矢量化的执行效率差异,在Jupyter Notebook环境中我们借助magic函数评估了两种方式在性能上的优劣:矢量化处理与非矢量化的逐个元素处理。

测试一:对10000个值在0~1000的随机数进行求和

复制代码
 %%timeit -n 100

    
 summary = 0
    
 for item in s:
    
     summary+=item
    
  
    
 %%timeit -n 100
    
 summary = np.sum(s)

结果为:

测试二:把所有随机数值加2:

复制代码
 %%timeit -n 10

    
 s = pd.Series(np.random.randint(0,1000,10000))
    
 for label, value in s.iteritems():
    
     s.loc[label]= value+2
    
  
    
 %%timeit -n 10
    
 s = pd.Series(np.random.randint(0,1000,10000))
    
 s+=2

结果为:

series属性中的索引标签被允许具有重复性;即同一个索引标签会被允许重复使用;当进行查询操作时若涉及多个相同的索引标签,则返回的对象仍是一个Series类型;

注意到在pandas中常使用的append方法,在其设计时就考虑到这一特性。具体来说,在调用该操作时并不会直接作用于原有的series对象上,并不会产生任何修改或影响。相反地会生成一个新的Series实例供后续使用这种方法的好处在于避免了对原始数据造成不必要的修改风险同时也能保证原有数据的安全性

二、The DataFrame Data Structure:

核心的数据结构是Pandas库的关键组成部分。它常用于处理数据分析和数据清洗的任务。databricks DataFrame API提供了类似数据库表的数据存储解决方案。不同区分数不同的行索引和列索引。将其想象为由共享相同键值对的一组Series构建而成的一个字典类型的复合体。实际上它是一个二维、带标签且可操作性强大的数组结构。

1.创建DataFrame:

使用一组series创建:

每个series代表DataFrame中的一行数据:

复制代码
 import pandas as pd

    
 purchase_1 = pd.Series({'Name': 'Chris',
    
                     'Item Purchased': 'Dog Food',
    
                     'Cost': 22.50})
    
 purchase_2 = pd.Series({'Name': 'Kevyn',
    
                     'Item Purchased': 'Kitty Litter',
    
                     'Cost': 2.50})
    
 purchase_3 = pd.Series({'Name': 'Vinod',
    
                     'Item Purchased': 'Bird Seed',
    
                     'Cost': 5.00})
    
 df = pd.DataFrame([purchase_1, purchase_2, purchase_3], index=['Store 1', 'Store 1', 'Store 2'])
    
 df.head()

使用一组dictionary创建:

当一个嵌套字典结构被用于生成一个数据框时,则该数据框的数据记录将被组织成一个二维表格的形式;其中外层键将成为表格中的列标题;而内层键则将作为每一行的具体数据字段;这样构建的数据框将会按照其行标签进行排序

复制代码
 pop = {'Nevada': {2001: 2.4, 2002: 2.9},'Ohio': {2000: 1.5, 2001: 1.7, 2002: 3.6}}

    
 frame3 = pd.DataFrame(pop)
    
 frame3

同样,在这种情况下,我们仍然可以采用 iloc 和 loc 属性来对 DataFrame 中的数据进行获取操作。需要注意的是,在这种情况下,默认情况下 iloc 和 loc 会根据传入的单一参数(即行索引值)来执行数据提取操作,并将返回 Series 或 DataFrame 对象。

需要注意的是,在一个DataFrame中,索引(index)和列名(column names)分别代表行和列的数据标识符,并且这些标识符在其值中可能存在重复性。

2.根据行、列获取数据:

如果我们向lociloc属性传递了两个参数,则其中第一个参数表示行的位置(即行索引值),第二个参数表示列的名称(即列名),此时将能够获取具体位置上的数据。

还有一个问题,如果我们想要根据列名来获取数据,那该怎么办?

方法一:将DataFrame进行装置,然后在loc属性进行获取;

例如,想要获取列名为Cost的所有数据:

但是不推荐使用这种方法,因为有时候这会带来一些bug。

方法二基于方括号操作符([ ])能够根据指定参数提取所需数据的同时,在 DataFrame 中每列均具有明确名称因此在使用这一操作时将避免出现类似 Series 中的操作错误此外这种数据提取方式类似于数据库中的投影运算

例如,还是获取列名为Cost的所有数据:

而且,我们还可以联动的使用方括号操作符("[]"):

例如:

不建议采用此方法。原因是返回的数据并非所选数据的投影而是其副本。这会导致一定的成本消耗。不仅在联动使用时容易出现故障问题(bugs)。

此外, 除了loc和iloc属性之外, 它们还可以执行分片操作。因为它们都是用于数据框中的行索引工具, 所以当调用时, 我们只需指定全部行. 通过传递两个参数来指定所需的选择范围. 在调用函数时, 首个参数应设为冒号:., 这样就能包含所有数据中的每一行. 接下来, 给第二个参数设置成想要的列可以选择单一字符串来表示某一整列的数据, 或者提供一个由多个字符串组成的列表以选取多列数据.

3.删除行或列:

移除行和列:可以通过drop函数实现数据的移除。需要注意的是,在调用该函数时,参数可以选择指定的行索引号或目标列名。然而,在使用过程中必须注意的一点是:drop函数不会修改原始的数据框(DataFrame),而是会返回一个新的数据框(DataFrame),该新数据框已完成了相应的移除操作。这种行为与append函数的行为非常相似。

drop函数的签名为:

copy_df.drop(labels, axis=0, level=None, inplace=False, errors='raise')

在数据框中,在axis参数设置为0时代表行(axis=1代表列);当inplace=True时会从原始dataframe中删除数据(inplace=False则不会执行此操作)。

还可以通过del关键字实现删除操作:这种删除操作不会返回任何值,并且直接作用于原始数据框上。

添加一列:

4.DataFrame的索引和载入:

在处理数据的过程中通常是这样的流程:首先将这些数据加载到一个DataFrame对象中;然后提取出感兴趣的具体行或列来进行后续操作;而Pandas通常返回的是原始数据结构的一个视图副本;这也就意味着,在对某些数据进行操作时实际上是在原有数据源上直接完成相关修改和计算过程

此外而言之

例如,我们从CSV文件中读取每个国家在奥运会中获得的奖牌的数目:

通过查看图形信息可知,在处理数据框时应当将第二位索引位置作为DataFrame对象中的行作为索引,并将第一行的数据设定为列名字段。具体实现时应指定index_col参数为0(即第二位索引位置),同时跳过前一行并指定列名字段以便后续的数据解析工作)。具体实现结果如图所示:

通过查看图表, 我们发现存在一些不太明确的数据符号, 因此我们需要清理数据文件. 为了清理数据文件, 我们可以通过对CSV文件进行处理, 同时也可以通过修改DataFrame的字段名称来达到目标.

5.Boolean Masking:

它是Numpy高效执行查询的核心机制。
实际上一个Boolean Mask本质上是一个数组,在这种情况下它的元素值仅为true或false。
然而,在一个布尔掩码中(即一个布尔Mask中),其元素值仅为true或false。我们可以通过将该布尔掩码应用于所需的DataFrame或Series来进行高效的数据查询操作。
如图所示。

例如,我们想得到在夏季奥运会上至少获得一枚金牌的国家:

方法一:

第一步,在夏季奥运会中至少赢得一枚奖牌时对应产出一个布尔掩模

第二步:借助where函数将Boolean Mask应用到Dataframe中,以便完成数据检索。

where函数使用Boolean Mask作为选择标准,并将该标准应用于DataFrame或Series上,从而生成与原始数据形状一致的结果

尽管在DataFrame中绝大多数的内置统计函数都能忽略NaN值的存在(即NaN被这些函数所忽略),但为了确保数据完整性与准确性,我们需要对NaN进行必要的处理;为此可以选择调用dropna函数来进行操作。

方法二:直接将Boolean Mask作为索引操作符(即方括号)的参数

此外,还能使用逻辑操作符对多个Boolean Mask进行操作,

6.处理DataFrame的index:

如前所述,在处理数据时我们可以应用到数据框(dataframe)和系列(series)。其本质上相当于为每一行分配了一个标识符。通过调用set_index函数可以修改数据框或系列的index信息。请注意这一点:调用set_index函数会丢弃现有的index信息。如果你希望保留原有index请先获取现有index属性并将其复制至新的列以便保存

我们可以通过rest_index函数将DataFrame的索引重新设置成数值形式:

此外,在pandas中存在一种多层次索引机制(...)。这一功能与关系型数据库中的复合主键具有相似性。通过设置set_index函数的一个参数为列表类型,则可实现这一目标。

同样地,我们也可以使用iloc、loc属性进行数据获取:

7.处理DataFrame中缺失的值:

全部评论 (0)

还没有任何评论哟~