介绍

在上一个教程中,我们学习了如何从 DataFrame 或 Series 中选取相关数据。如教程中展示的那样,从数据表示中提取正确的数据对于完成工作至关重要。
然而,数据并不总是直接以我们期望的格式从内存中出来。为了完成手头的任务,我们不得不自己做更多的数据重格式化工作。本教程将涵盖我们可以应用于我们的数据的不同的操作,以使输入的数据恰好满足要求。
我们仍将使用葡萄酒杂志的数据进行演示。

  1. import pandas as pd
  2. reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
  3. print(reviews)
  1. country ... winery
  2. 0 Italy ... Nicosia
  3. 1 Portugal ... Quinta dos Avidagos
  4. 2 US ... Rainstorm
  5. 3 US ... St. Julian
  6. 4 US ... Sweet Cheeks
  7. ... ... ... ...
  8. 129966 Germany ... Dr. H. Thanisch (Erben Müller-Burggraef)
  9. 129967 US ... Citation
  10. 129968 France ... Domaine Gresser
  11. 129969 France ... Domaine Marcel Deiss
  12. 129970 France ... Domaine Schoffit
  13. [129971 rows x 13 columns]

Summary函数

Pandas提供了许多简单的“Summary函数”(不是官方名称),这些函数以某种有用的方式重构数据。
例如,descripe()方法:

  1. DataFrame.describe(percentiles=None, include=None, exclude=None, datetime_is_numeric=False)

生成描述性统计,包括总结数据集分布的中心趋势、分散性和形状的统计数据,不包括NaN值。
分析数值系列和对象系列,以及混合数据类型的数据帧列集。输出将根据所提供的内容而变化。

  1. import pandas as pd
  2. reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
  3. print(reviews.points.describe())

此方法生成给定列的属性的高级汇总。它是类型感知的,这意味着它的输出根据输入的数据类型而改变。
总结数据集分布的中心趋势,分散和形状,不包括NaN值。
百分位数:统计学术语,如果将一组数据从小到大排序,并计算相应的累计百分位,则某一百分位所对应数据的值就称为这一百分位的百分位数。可表示为:一组n个观测值数值大小排列。如,处于p%位置的值称第p百分位数

  1. count 129971.000000
  2. mean 88.447138
  3. std 3.039730
  4. min 80.000000
  5. 25% 86.000000
  6. 50% 88.000000
  7. 75% 91.000000
  8. max 100.000000
  9. Name: points, dtype: float64
  1. DataFrame.count
  2. Count number of non-NA/null observations.
  3. DataFrame.max
  4. Maximum of the values in the object.
  5. DataFrame.min
  6. Minimum of the values in the object.
  7. DataFrame.mean
  8. Mean of the values.
  9. DataFrame.std
  10. Standard deviation of the observations.
  11. DataFrame.select_dtypes
  12. Subset of a DataFrame including/excluding columns based on their dtype.

上面的输出只对数值数据有意义;对于字符串数据,我们得到的是:

  1. import pandas as pd
  2. reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
  3. print(reviews.taster_name.describe())
  1. count 103727
  2. unique 19
  3. top Roger Voss
  4. freq 25514
  5. Name: taster_name, dtype: object

如果您想获得关于DataFrame 或 Series中某列的一些特定的简单汇总统计信息,通常会有一个非常好用的pandas函数来实现它。
例如,要查看分配的点数的平均值(例如,葡萄酒评分的平均值),我们可以使用mean()函数:

  1. import pandas as pd
  2. reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
  3. print(reviews.points.mean()) # 88.44713820775404

要查看唯一值的列表,可以使用unique()函数(去除重复元素):

  1. import pandas as pd
  2. reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
  3. print(reviews.taster_name.unique())
  1. ['Kerin O’Keefe' 'Roger Voss' 'Paul Gregutt' 'Alexander Peartree'
  2. 'Michael Schachner' 'Anna Lee C. Iijima' 'Virginie Boone' 'Matt Kettmann'
  3. nan 'Sean P. Sullivan' 'Jim Gordon' 'Joe Czerwinski'
  4. 'Anne Krebiehl\xa0MW' 'Lauren Buzzeo' 'Mike DeSimone' 'Jeff Jenssen'
  5. 'Susan Kostrzewa' 'Carrie Dykes' 'Fiona Adams' 'Christina Pickard']

要查看唯一值的列表以及它们在数据集中出现的频率,可以使用value_counts()方法:

  1. import pandas as pd
  2. reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
  3. print(reviews.taster_name.value_counts())
  1. Roger Voss 25514
  2. Michael Schachner 15134
  3. Kerin OKeefe 10776
  4. Virginie Boone 9537
  5. Paul Gregutt 9532
  6. Matt Kettmann 6332
  7. Joe Czerwinski 5147
  8. Sean P. Sullivan 4966
  9. Anna Lee C. Iijima 4415
  10. Jim Gordon 4177
  11. Anne Krebiehl MW 3685
  12. Lauren Buzzeo 1835
  13. Susan Kostrzewa 1085
  14. Mike DeSimone 514
  15. Jeff Jenssen 491
  16. Alexander Peartree 415
  17. Carrie Dykes 139
  18. Fiona Adams 27
  19. Christina Pickard 6
  20. Name: taster_name, dtype: int64

Maps

映射是从数学中借用的一个术语,用于表示一个函数,它接受一组值并将它们“映射”到另一组值。在数据科学中,我们经常需要从现有的数据中创建新的表示形式,或者将数据从现在的格式转换为我们希望以后使用的格式。Maps是处理这项工作的工具,对完成你的工作极其重要!
经常会使用的有两种映射方法。
map()是第一个方法,稍微简单一点。例如,假设我们知道葡萄酒的分数与平均分差值。我们可以这样做:

  1. import pandas as pd
  2. reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
  3. review_points_mean = reviews.points.mean()
  4. print(reviews.points.map(lambda p: p - review_points_mean)) # 减去与平均分值的差
  1. 0 -1.447138
  2. 1 -1.447138
  3. 2 -1.447138
  4. 3 -1.447138
  5. 4 -1.447138
  6. ...
  7. 129966 1.552862
  8. 129967 1.552862
  9. 129968 1.552862
  10. 129969 1.552862
  11. 129970 1.552862
  12. Name: points, Length: 129971, dtype: float64

传递给map() 的函数应该能从序列中获得单一的值(在上面的示例中是一个点值),并返回该值的转换。map()返回一个新序列,其中所有值都已由函数转换。
如果我们想通过调用每一行的自定义方法来转换整个DataFrame,apply()是等效的方法。

  1. import pandas as pd
  2. reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
  3. review_points_mean = reviews.points.mean()
  4. def remean_points(row):
  5. row.points = row.points - review_points_mean
  6. return row
  7. print(reviews.apply(remean_points, axis='columns'))
  1. country ... winery
  2. 0 Italy ... Nicosia
  3. 1 Portugal ... Quinta dos Avidagos
  4. 2 US ... Rainstorm
  5. 3 US ... St. Julian
  6. 4 US ... Sweet Cheeks
  7. ... ... ... ...
  8. 129966 Germany ... Dr. H. Thanisch (Erben Müller-Burggraef)
  9. 129967 US ... Citation
  10. 129968 France ... Domaine Gresser
  11. 129969 France ... Domaine Marcel Deiss
  12. 129970 France ... Domaine Schoffit
  13. [129971 rows x 13 columns]

如果我们通过 axis = ‘index’ 调用 reviews.apply(),那么我们需要传递一个函数来转换每一列,而不是传递一个函数来转换每一行。
注意,map() 和 apply() 会返回一个新的、转换过的 Series 和 DataFrames,他们不会修改被调用的原始数据。如果我们看第一行评价,我们可以看到它仍然是它原始的值。

  1. import pandas as pd
  2. reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
  3. review_points_mean = reviews.points.mean()
  4. def remean_points(row):
  5. row.points = row.points - review_points_mean
  6. return row
  7. print(reviews.apply(remean_points, axis='columns'))
  8. print(reviews.head(1))
  1. country ... winery
  2. 0 Italy ... Nicosia
  3. [1 rows x 13 columns]

Pandas提供了许多常见的内置映射操作。例如,这里有一种更快的方法来重新计算points列的平均值:

  1. import pandas as pd
  2. reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
  3. review_points_mean = reviews.points.mean()
  4. print(reviews.points - review_points_mean)
  1. 0 -1.447138
  2. 1 -1.447138
  3. 2 -1.447138
  4. 3 -1.447138
  5. 4 -1.447138
  6. ...
  7. 129966 1.552862
  8. 129967 1.552862
  9. 129968 1.552862
  10. 129969 1.552862
  11. 129970 1.552862
  12. Name: points, Length: 129971, dtype: float64

在这段代码中,我们在左侧的多个值(序列中的所有值)和右侧的单个值(平均值)之间执行操作。Pandas查看这个表达式,发现我们必须从数据集中的每个值中减去该平均值。
如果我们在等长的序列之间执行这些操作,Pandas也会知道该怎么做。例如,在数据集中合并国家和地区信息的一种简单方法是执行以下操作:

  1. import pandas as pd
  2. reviews = pd.read_csv("../data/winemag-data-130k-v2.csv", index_col=0)
  3. print(reviews.country + " - " + reviews.region_1)
  1. 0 Italy - Etna
  2. 1 NaN
  3. 2 US - Willamette Valley
  4. 3 US - Lake Michigan Shore
  5. 4 US - Willamette Valley
  6. ...
  7. 129966 NaN
  8. 129967 US - Oregon
  9. 129968 France - Alsace
  10. 129969 France - Alsace
  11. 129970 France - Alsace
  12. Length: 129971, dtype: object

这些运算符比map()或apply()更快,因为它们使用pandas内置于的加速机制。所有标准的Python操作符(>、<、=,等等)都以这种方式工作。
但是,它们不像map()或apply()那样灵活,后者可以执行更高级的操作,例如仅通过加法和减法是做不到的条件运算和逻辑运算。