pandas中的series和dataframe

pandas Series 和 DataFrame

Series

Series是一个增强的一维数组。数组仅使用从零开始的整数索引,而Series支持自定义索引,甚至包括字符串等非整数索引。Series还提供额外的功能,使它们能更方便地完成许多面向数据科学的任务。例如,考虑到Series中可能有缺失数据,默认情况下,许多Series操作都会忽略缺失数据。

使用默认索引创建Series

默认情况下,一个Series的整数索引是从0开始顺序编号的。

下面从一个整数列表中创建一个学生成绩的Series:

In [1]: import pandas as pd
In [2]: grades = pd.Series([87,100,94])

初始化变量也可以是元组、字典、数组、另一个Series或单个值。

Series 的显示

pandas以两列格式显示Series,其索引在左列中左对齐,而值在右列中右对齐。在列出Series元素之后,pandas显示了底层array元素的数据类型(dtype):

In [10]: grades
Out[10]:
0     87
1    100
2     94
dtype: int64

可以看到,与以相同的两列格式显示列表的对应代码相比,以这种格式显示Series非常容易。

创建一个内部元素值相同的Series

可以创建具有相同元素值的Series:

In [12]: pd.Series(98.6,range(3))
Out[12]:
0    98.6
1    98.6
2    98.6
dtype: float64

第二个参数是一个一维的可迭代对象(例如列表、数组或范围),它包含了Series的索引。索引的数量决定了元素的数量。

访问Series中的元素

可以通过包含索引的方括号来访问Series的元素:

In [11]: grades[0]
Out[11]: 87

为Series生成描述性统计信息

Series提供了许多用于常见任务(包括生成各种描述性统计信息)的方法。以下列出了count(元素个数)、mean(均值)、min(最小值)、max(最大值)和std(标准偏差)方法:

In [3]: grades.count()
Out[3]: 3

In [4]: grades.mean()
Out[4]: 93.66666666666667

In [5]: grades.min()
Out[5]: 87

In [6]: grades.max()
Out[6]: 100

In [7]: grades.std()
Out[7]: 6.506407098647712

这些都是函数式约简。调Series的describe方法会给出所有的统计信息以及更多信息:

In [9]: grades.describe()
Out[9]:
count      3.000000
mean      93.666667
std        6.506407
min       87.000000
25%       90.500000
50%       94.000000
75%       97.000000
max      100.000000
dtype: float64

其中,25%、50%和75%是四分位数

  • 50%表示排序值的中值。
  • 25%代表排序后前一半值的中值。
  • 75%代表排序后后一半值的中值。

​ 对于四分位数,如果有两个中间元素,那么它们的平均值就是该四分位数的中值。而我们Series中只有三个值,因此25%的四分位数是87和94的平均值,而75%的四分位数是94和100的平均值。四分位数****间距是75%的四分位数减去25%的四分位数,这是像标准偏差和方差的另一种度量离散度的方法。当然,四分位数和四分位数间距在较大的数据集中会更有用。

创建带自定义索引的Series

可以使用关键字参数index来指定自定义索引:

In [14]: grades = pd.Series([87,100,94],index=['Wally','Eva','Sam'])

In [15]: grades
Out[15]:
Wally     87
Eva      100
Sam       94
dtype: int64

在本例中,我们使用了字符串作为索引,但是也可以使用其他不可变类型,包括不是从0开始的整数和非连续整数。同样,请再次注意pandas如何精确地格式化一个Series以供显示。

字典作为初始化值

如果使用字典初始化Series,则它的键将成为Series的索引,它的值会被设定为Series的元素值:

In [16]: grades = pd.Series({'Wally':87,'Eva':100,'Sam':94})

In [17]: grades
Out[17]:
Wally     87
Eva      100
Sam       94
dtype: int64

使用自定义索引访问Series中的元素

在使用自定义索引的Series中,可以通过包含自定义索引值的方括号来访问单个元素:

In [19]: grades['Eva']
Out[19]: 100

如果自定义索引是可以表示有效Python标识符的字符串,则pandas会自动将它们添加到Series中,作为可以通过点(.)访问的属性:

In [20]: grades.Wally
Out[20]: 87

Series还具有内置属性。例如,dtype属性返回底层array的元素类型:

In [24]: grades.dtypes
Out[24]: dtype('int64')

values属性返回底层array:

In [23]: grades.values
Out[23]: array([ 87, 100,  94], dtype=int64)

创建一个字符串Series

如果一个Series包含字符串,那么可以使用它的str属性来调用元素上的字符串方法。首先,让我们创建一个硬件相关的字符串Series:

In [26]: hardware = pd.Series(['Hammer','Saw','Wrench'])

In [27]: hardware
Out[27]:
0    Hammer
1       Saw
2    Wrench
dtype: object

请注意,pandas还会将字符串元素值右对齐,并且字符串的dtype是object。

判断Series中是否包含某字符

​ 调用每个元素上的字符串方法contains来确定每个元素的值是否包含’a’

In [28]: hardware.str.contains('a')
Out[28]:
0     True
1     True
2    False
dtype: bool

​ pandas返回了一个包含布尔值的新Series,该值指示了contains方法对每个元素的执行结果—索引2(‘Wrench’)处的元素不包含’a’,因此其在所得Series中的对应位置的元素为False。请注意,pandas在内部处理了迭代—这是函数式编程的另一个示例。str属性提供了许多类似于Python字符串类型的字符串处理方法。有关方法列表,参见:this link
​ 以下使用字符串方法upper生成一个新的Series,其中包含hardware变量中每个元素的大写版本:

In [29]: hardware.str.upper()
Out[29]:
0    HAMMER
1       SAW
2    WRENCH
dtype: object

DataFrame

​ DataFrame是增强的二维数组。与Series类似,DataFrame可以具有自定义的行和列索引,并提供额外的操作和功能,使其能更方便地执行许多面向数据科学的任务。DataFrame还支持缺失数据情况下的处理。DataFrame中的每一列都是一个Series。代表每个列的Series可能包含不同的元素类型,在我们讨论将数据集加载到DataFrame时,会看到这一点。

从字典中创建一个DataFrame

从字典中创建一个DataFrame让我们从字典中创建一个DataFrame,它表示学生在三次考试中的成绩:

In [32]: grades_dict = {'Wally':[87,96,70],'Eva':[100,87,90],'Sam':[94,77,90],'Katie':[100,81,82],'Bob':[83,65,85]}

In [33]: grades = pd.DataFrame(grades_dict)

In [34]: grades
Out[34]:
   Wally  Eva  Sam  Katie  Bob
0     87  100   94    100   83
1     96   87   77     81   65
2     70   90   90     82   85

pandas以表格格式显示DataFrame,其中索引在索引列中左对齐,其余列的值右对齐。字典的键变成列名,而与每个键相关联的值成为对应列中的元素值。稍后,我们将展示如何“翻转”行和列。默认情况下,行索引是从0开始自动生成的整数。

使用index属性自定义DataFrame的索引

在创建DataFrame时,可以使用index关键字参数指定自定义索引,如下所示:

pd.DataFrame(grades_dict,index=['Test1','Test2','Test3'])

​ 使用index属性将DataFrame的索引从连续整数更改为标签:

In [35]: grades.index = ['Test1','Test2','Test3']

In [36]: grades
Out[36]:
       Wally  Eva  Sam  Katie  Bob
Test1     87  100   94    100   83
Test2     96   87   77     81   65
Test3     70   90   90     82   85

在指定索引时,必须提供元素数等于DataFrame中的行数的一维合集;否则,将引发ValueError。Series还提供了一个index属性,用于更改现有Series的索引。

访问DataFrame元素的列

​ 使用pandas的一个好处是可以通过多种不同的方式方便快速地查看数据,包括选择部分数据。让我们先按名称获取Eva的成绩,这会将她所在的列显示为一个Series:

In [37]: grades['Eva']
Out[37]:
Test1    100
Test2     87
Test3     90
Name: Eva, dtype: int64

如果DataFrame的列名字符串是有效的Python标识符,则可以将它们用作属性。让我们用Sam属性来得到Sam的成绩:

In [38]: grades.Sam
Out[38]:
Test1    94
Test2    77
Test3    90
Name: Sam, dtype: int64

通过loc和iloc属性选择行

尽管DataFrame支持使用[]建立索引的功能,但pandas的文档建议使用属性loc、iloc、at和iat来进行行操作。这些属性已被优化为专门用于访问DataFrame,还能提供除了[]之外的其他功能。此外,文档还指出,使用[]建立索引通常会产生数据副本,如果试图通过赋值给[]操作的结果来为DataFrames设定新值,则会导致一个逻辑错误。
可以使用DataFrame的loc属性通过行标签访问行。下面列出了’Test1’行中的所有成绩:

In [40]: grades.loc['Test1']
Out[40]:
Wally     87
Eva      100
Sam       94
Katie    100
Bob       83
Name: Test1, dtype: int64

还可以使用iloc属性通过基于零的整数索引访问行(iloc中的i表示它与整数索引一起使用)。下面列出了第二行中的所有成绩:

In [41]: grades.iloc[1]
Out[41]:
Wally    96
Eva      87
Sam      77
Katie    81
Bob      65
Name: Test2, dtype: int64

通过带有loc和iloc属性的切片和列表选择行

​ 索引可以是一个切片。当使用包含带有loc的标签的切片时,指定的范围包括切片右端的索引(‘Test3’):

In [43]: grades.loc['Test1':'Test3']
Out[43]:
       Wally  Eva  Sam  Katie  Bob
Test1     87  100   94    100   83
Test2     96   87   77     81   65
Test3     70   90   90     82   85

​ 当将iloc属性与包含整数索引的切片一起使用时,指定的范围不包括切片右端的索引(2):

In [44]: grades.iloc[0:2]
Out[44]:
       Wally  Eva  Sam  Katie  Bob
Test1     87  100   94    100   83
Test2     96   87   77     81   65

要选择特定的行,请在loc或iloc属性中使用列表代替切片:

In [45]: grades.loc[['Test1','Test3']]
Out[45]:
       Wally  Eva  Sam  Katie  Bob
Test1     87  100   94    100   83
Test3     70   90   90     82   85

In [46]: grades.iloc[[0,2]]
Out[46]:
       Wally  Eva  Sam  Katie  Bob
Test1     87  100   94    100   83
Test3     70   90   90     82   85
选择行与列的子集

到目前为止,我们只选择了整行。可以使用两个切片、两个列表或切片和列表的组合来选择行与列,从而专注于DataFrame的一个小子集。
假设只想查看Test1和Test2中Eva和Katie的成绩,可以通过使用带有两个连续行的切片的loc和两个非连续列的列表来实现:

In [48]: grades.loc['Test1':'Test2',['Eva','Katie']]
Out[48]:
       Eva  Katie
Test1  100    100
Test2   87     81

切片’Test1’:'Test2’选择索引为Test1和Test2的这两行。列表[‘Eva’,‘Katie’]表示仅从这两列中选择相应的成绩。
让我们使用带有列表和切片的iloc来选择第一个和第三个测试成绩,并获取这些测试成绩的前三列:

In [49]: grades.iloc[[0,2],0:3]
Out[49]:
       Wally  Eva  Sam
Test1     87  100   94
Test3     70   90   90

布尔索引

pandas更强大的选择功能之一是布尔索引。例如,让我们选择所有的A等成绩,即大于或等于90分的成绩:

In [50]: grades[grades >= 90]
Out[50]:
       Wally    Eva   Sam  Katie  Bob
Test1    NaN  100.0  94.0  100.0  NaN
Test2   96.0    NaN   NaN    NaN  NaN
Test3    NaN   90.0  90.0    NaN  NaN

pandas检查每个成绩,以确定其值是否大于或等于90,如果是,则令其包含在新的DataFrame中。条件为False的成绩在新的DataFrame中表示为NaN(不是数字)。NaN是pandas用来表示缺失值的符号。
让我们选择出分数为80~89的所有的B等成绩:

In [51]: grades[(grades >= 80) & (grades < 90)]
Out[51]:
       Wally   Eva  Sam  Katie   Bob
Test1   87.0   NaN  NaN    NaN  83.0
Test2    NaN  87.0  NaN   81.0   NaN
Test3    NaN   NaN  NaN   82.0  85.0

pandas的布尔索引使用Python位运算符&(按位与)而不是布尔运算符and来组合多个条件。对于or条件,使用|(按位或)。NumPy还支持arrays的布尔索引,但始终返回仅包含满足条件的值的一维数组。

通过行和列访问特定的DataFrame单元格

可以使用DataFrame的at和iat属性从DataFrame获取单个值。像loc和iloc一样,at使用标签,而iat使用整数索引。在每种情况下,行和列的索引必须用逗号分隔。让我们选择出Eva的Test2成绩(87)和Wally的Test3成绩(70):

In [52]: grades.at['Test2','Eva']
Out[52]: 87

In [53]: grades.iat[2,0]
Out[53]: 70

还可以为特定的元素分配新值。让我们使用at将Eva的Test2成绩更改为100,然后使用iat将其更改回87:

In [54]: grades.at['Test2','Eva']=100

In [55]: grades.at['Test2','Eva']
Out[55]: 100

In [56]: grades.iat[1,2] = 87

In [57]: grades.iat[1,2]
Out[57]: 87

描述性统计

Series和DataFrame都有一个describe方法,该方法计算数据的基本描述性统计并将结果以DataFrame的形式返回。在DataFrame中,统计数据是按列计算的(我们很快将看到如何翻转行和列):

In [58]: grades.describe()
Out[58]:
           Wally         Eva        Sam       Katie        Bob
count   3.000000    3.000000   3.000000    3.000000   3.000000
mean   84.333333   96.666667  90.333333   87.666667  77.666667
std    13.203535    5.773503   3.511885   10.692677  11.015141
min    70.000000   90.000000  87.000000   81.000000  65.000000
25%    78.500000   95.000000  88.500000   81.500000  74.000000
50%    87.000000  100.000000  90.000000   82.000000  83.000000
75%    91.500000  100.000000  92.000000   91.000000  84.000000
max    96.000000  100.000000  94.000000  100.000000  85.000000

默认情况下,pandas使用浮点值计算描述性统计信息,并以六位数字的精度显示它们。可以使用pandas的set_option函数控制精度和其他默认设置:

In [59]: pd.set_option('precision',2)

In [60]: grades.describe()
Out[60]:
       Wally     Eva    Sam   Katie    Bob
count   3.00    3.00   3.00    3.00   3.00
mean   84.33   96.67  90.33   87.67  77.67
std    13.20    5.77   3.51   10.69  11.02
min    70.00   90.00  87.00   81.00  65.00
25%    78.50   95.00  88.50   81.50  74.00
50%    87.00  100.00  90.00   82.00  83.00
75%    91.50  100.00  92.00   91.00  84.00
max    96.00  100.00  94.00  100.00  85.00

对于学生成绩,这些统计数据中最重要的可能是平均值。只需在DataFrame上调用mean方法即可为每名学生计算该值:

In [61]: grades.mean()
Out[61]:
Wally    84.33
Eva      96.67
Sam      90.33
Katie    87.67
Bob      77.67
dtype: float64

接下来,我们将展示如何通过一行附加代码来获得每个测试中所有学生的平均成绩。

使用T属性转置DataFrame

可以使用T属性快速地转置行和列—这样行就变成了列,列就变成了行:

In [62]: grades.T
Out[62]:
       Test1  Test2  Test3
Wally     87     96     70
Eva      100    100     90
Sam       94     87     90
Katie    100     81     82
Bob       83     65     85

T属性返回DataFrame的转置视图(不是副本)。
假设不是按学生获取摘要统计信息,而是针对测试来进行分析。对此,我们只需在grades.T上调用describe,如下所示:

In [63]: grades.T.describe()
Out[63]:
        Test1   Test2  Test3
count    5.00    5.00   5.00
mean    92.80   85.80  83.40
std      7.66   13.81   8.23
min     83.00   65.00  70.00
25%     87.00   81.00  82.00
50%     94.00   87.00  85.00
75%    100.00   96.00  90.00
max    100.00  100.00  90.00

要查看每个测试中所有学生的平均成绩,只需在T属性上调用mean:

In [64]: grades.T.mean()
Out[64]:
Test1    92.8
Test2    85.8
Test3    83.4
dtype: float64

按行索引排序

通常会对数据进行排序,以提高可读性。可以根据DataFrame的索引或值对其行或列进行排序。让我们使用sort_index及其关键字参数ascending=False(默认情况下是按升序排序)对各行按行索引降序排序。这将返回一个包含已排序数据的新DataFrame:

In [65]: grades.sort_index(ascending=False)
Out[65]:
       Wally  Eva  Sam  Katie  Bob
Test3     70   90   90     82   85
Test2     96  100   87     81   65
Test1     87  100   94    100   83

按列索引排序

现在根据列名按升序(从左到右)排序。传递axis=1关键字参数表示我们希望依据列索引进行排序,而不是行索引—axis=0(默认值)表示按行索引排序:

In [67]: grades.sort_index(axis=1)
Out[67]:
       Bob  Eva  Katie  Sam  Wally
Test1   83  100    100   94     87
Test2   65  100     81   87     96
Test3   85   90     82   90     70

按列元素值排序

假定想按降序查看Test1的成绩,以便可以按分数从高到低的顺序查看学生的姓名。对此,可以按以下方式调用sort_values方法:

In [66]: grades.sort_values(by='Test1',axis=1,ascending=False)
Out[66]:
       Eva  Katie  Sam  Wally  Bob
Test1  100    100   94     87   83
Test2  100     81   87     96   65
Test3   90     82   90     70   85

by和axis关键字参数共同决定哪些值将被排序。在本例中,我们根据Test1的列值(axis=1)进行排序。
当然,如果成绩和名称位于一列中,则可能更易于阅读,因此我们可以对转置的DataFrame进行排序。在这里,我们不需要指定axis关键字参数,因为默认情况下sort_values对指定列中的数据进行排序:

In [68]: grades.T.sort_values(by='Test1',ascending=False)
Out[68]:
       Test1  Test2  Test3
Eva      100    100     90
Katie    100     81     82
Sam       94     87     90
Wally     87     96     70
Bob       83     65     85

最后,由于只需要对Test1的成绩排序,所以可能根本不想看到其他测试。为此,让我们把选择和排序结合起来:

In [69]: grades.loc['Test1'].sort_values(ascending=False)
Out[69]:
Eva      100
Katie    100
Sam       94
Wally     87
Bob       83
Name: Test1, dtype: int64
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值