如果你觉得内容对你有帮助,请在 GitHub 上点个 star 吧!

2.2. Series 与 DataFrame#

pandas 的核心数据结构有两个: Series 和 DataFrame。

import pandas as pd

Series#

在 pandas 中,Series 是一种一维的带标签的 数组状 数据结构。

../_images/Series.svg

图 2.1 Series#

我们创建一个 Series,这个数组有 4 个数,并命名为 my_series

s = pd.Series([1, 2, 3, 4], name = 'my_series')

Series 是一个数组状数据结构,其实就是 章节 1.2 中的 ndarray。 数组最重要的结构是索引(Index)。Index 主要用于标记第几个位置存储什么数据。pd.Series() 中不指定 Index 参数时,默认从 0 开始,逐一自增,形如: 0,1,…

  • Series 支持计算操作。

s * 100
0    100
1    200
2    300
3    400
Name: my_series, dtype: int64
  • Series 支持描述性统计。比如,获得所有统计信息。

s.describe()
count    4.000000
mean     2.500000
std      1.290994
min      1.000000
25%      1.750000
50%      2.500000
75%      3.250000
max      4.000000
Name: my_series, dtype: float64

计算平均值,中位数和标准差。

s.mean()
2.5
s.median()
2.5
s.std()
1.2909944487358056
  • Series 的索引很灵活。

s.index = ['number1','number2','number3','number4']

这时,Series 就像一个 Python 中的字典 dict,可以使用像 dict 一样的语法来访问 Series 中的元素,其中 index 相当于 dict 的键 key。例如,使用 [] 操作符访问 number1 对应的值。

s['number1']
1

又例如,使用 in 表达式判断某个索引是否在 Series 中。

'number1' in s
True

DataFrame#

DataFrame 可以简单理解为一个 Excel 表,有很多列和很多行,如 图 2.2 所示。 DataFrame 的列(column)表示一个字段;DataFrame 的行(row)表示一条数据。DataFrame 常被用来分析像 Excel 这样的、有行和列的表格类数据。Excel 也正在兼容 DataFrame,使得用户在 Excel 中进行 pandas 数据处理与分析。

../_images/DataFrame.svg

图 2.2 DataFrame 示意图#

创建 DataFrame#

创建一个 DataFrame 有很多方式,比如从列表、字典、文件中读取数据,并创建一个 DataFrame

  • 基于列表创建

names = ['Alice', 'Bob', 'Charlie']
ages = [25, 30, 22]
cities = ['New York', 'San Francisco', 'Los Angeles']
data = {'Name': names, 'Age': ages, 'City': cities}
df = pd.DataFrame(data)
  • 基于字典创建

data = {'Column1': [1, 2], 'Column2': [3, 4]}
df = pd.DataFrame(data)
  • 基于文件创建

图 2.3 所示,pandas 可以读取不同类型的文件,进行处理,最后持久化地写入不同类型的文件中。

../_images/file.svg

图 2.3 文件读取/写入#

对于不同类型的文件,使用不同的函数,比如 read_csv 读取 csv 类型的数据。df = pd.read_csv('/path/file.csv') 用来读取一个 csv 文件,df =  pd.read_excel('/path/file.xlsx') 用来读取一个 Excel 文件。

Note

注:csv 文件一般由很多个 column 组成,使用 pd.read_csv 时,默认每个 column 之间的分隔符为逗号(,),pd.read_table 默认分隔符为换行符。这些函数还支持许多其他参数,可以使用 help() 函数查看。

同样地,我们最终也可以将处理过的 DataFrame 写入文件即以文件的格式输出,例:df.to_excel(‘/path/file.xlsx’)则输出为excel文件。

计算统计量#

前面我们讲过对 Series 对象我们可以计算统计量,而 DataFrame 是由一列列 Series 对象构成的,自然也可以做相应的计算。

  • 对某一列计算相应统计量,本质上还是对 Series 对象做统计量计算,如 图 2.4

../_images/s1.svg

图 2.4 对 Dataframe 一列对象做统计量#

例:对 df 的第一列求平均值。(DataFrame 对象的切片操作后续会详细讲解。)

print("------- df is -------\n{}".format(df))
print("------- Column1.mean() -------\n")
print(df[['Column1']].mean())
------- df is -------
   Column1  Column2
0        1        3
1        2        4
------- Column1.mean() -------

Column1    1.5
dtype: float64
  • 对某几列计算相应统计量。

../_images/s2.svg

图 2.5 对 Dataframe 几列对象做统计量#

例:对 df 的第一列和第二列进行描述性统计。

由于这里的 df 只有两列,也可以直接对整个 DataFrame 对象操作,即等价于 df.describe()

df[['Column1','Column2']].describe()
Column1 Column2
count 2.000000 2.000000
mean 1.500000 3.500000
std 0.707107 0.707107
min 1.000000 3.000000
25% 1.250000 3.250000
50% 1.500000 3.500000
75% 1.750000 3.750000
max 2.000000 4.000000
  • 使用 DataFrame.agg() 方法计算特定的统计量组合。

有时候我们对一列需要指定的一些统计量,对不同列又有不同的需求,则可以使用 DataFrame.agg() 方法,传入字典参数,key 为列名,value 为需要的统计量的列表。

例:对 df 的第一列获得最小值 / 最大值 / 中位数 / 偏度,对第二列获得最小值 / 最大值 / 中位数 / 均值。

df.agg({
    'Column1':['min','max','median','skew'],
    'Column2':['min','max','median','mean']   
})
Column1 Column2
min 1.0 3.0
max 2.0 4.0
median 1.5 3.5
skew NaN NaN
mean NaN 3.5

案例:PWT#

PWT 是一个经济学数据库,用于比较国家和地区之间的宏观经济数据,该数据集包含了各种宏观经济指标,如国内生产总值(GDP)、人均收入、劳动力和资本等因素,以及价格水平、汇率等信息。我们先下载,并使用 pandas 简单探索该数据集。

Hide code cell content
import os
import urllib.request
import zipfile

folder_path = os.path.join(os.getcwd(), "../data/pwt")
download_url = "https://www.rug.nl/ggdc/docs/pwt70_06032011version.zip"
file_name = download_url.split("/")[-1]
zip_file_path = os.path.join(folder_path, file_name)
if not os.path.exists(folder_path):
    os.makedirs(folder_path)

if not os.path.exists(zip_file_path):
    urllib.request.urlretrieve(download_url, zip_file_path)
    with zipfile.ZipFile(zip_file_path, 'r') as zip_ref:
        zip_ref.extractall(folder_path)
文件夹已存在,无需操作。

查看数据#

  • 使用 read_csv() 读取数据。

import pandas as pd

df = pd.read_csv(os.path.join(folder_path, "pwt70_w_country_names.csv"))
  • head() 函数可以指定查看前 n 行。

n = 5
df.head(n)
country isocode year POP XRAT Currency_Unit ppp tcgdp cgdp cgdp2 ... kg ki openk rgdpeqa rgdpwok rgdpl2wok rgdpl2pe rgdpl2te rgdpl2th rgdptt
0 Afghanistan AFG 1950 8150.368 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
1 Afghanistan AFG 1951 8284.473 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2 Afghanistan AFG 1952 8425.333 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
3 Afghanistan AFG 1953 8573.217 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
4 Afghanistan AFG 1954 8728.408 NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

5 rows × 37 columns

  • tail() 函数指定查看后 n 行。

df.tail(n)
country isocode year POP XRAT Currency_Unit ppp tcgdp cgdp cgdp2 ... kg ki openk rgdpeqa rgdpwok rgdpl2wok rgdpl2pe rgdpl2te rgdpl2th rgdptt
11395 Zimbabwe ZWE 2005 11639.470 2.236364e+01 Zimbabwe Dollar 39.482829 1968.205961 169.097559 184.183929 ... 6.995770 9.376272 89.399427 214.739197 418.970867 418.970867 NaN 390.907086 NaN 169.097559
11396 Zimbabwe ZWE 2006 11544.326 1.643606e+02 Zimbabwe Dollar 384.899651 2132.305773 184.705956 192.953943 ... 7.648020 14.986823 81.697014 217.543648 424.754259 407.262097 NaN 377.352394 NaN 179.368685
11397 Zimbabwe ZWE 2007 11443.187 9.675781e+03 Zimbabwe Dollar 38583.323960 2107.937100 184.208918 198.215361 ... 8.387106 15.787322 84.483374 202.707080 396.486201 376.163064 NaN 345.764991 NaN 173.113448
11398 Zimbabwe ZWE 2008 11350.000 6.715424e+09 Zimbabwe Dollar 38723.957740 1772.209867 156.141839 162.112294 ... 7.685312 13.444449 85.117130 174.178806 343.159758 332.649861 NaN 302.945712 NaN 142.329054
11399 Zimbabwe ZWE 2009 11383.000 1.400000e+17 Zimbabwe Dollar 40289.958990 1906.049843 167.447056 174.419700 ... 7.905525 14.743667 83.749534 182.613004 NaN NaN NaN 314.171069 NaN 151.435285

5 rows × 37 columns

  • info() 函数可以查看数据基本信息,包括字段类型和非空值计数。

df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 11400 entries, 0 to 11399
Data columns (total 37 columns):
 #   Column         Non-Null Count  Dtype  
---  ------         --------------  -----  
 0   country        11400 non-null  object 
 1   isocode        11400 non-null  object 
 2   year           11400 non-null  int64  
 3   POP            11398 non-null  float64
 4   XRAT           10163 non-null  float64
 5   Currency_Unit  10163 non-null  object 
 6   ppp            8745 non-null   float64
 7   tcgdp          8745 non-null   float64
 8   cgdp           8745 non-null   float64
 9   cgdp2          8745 non-null   float64
 10  cda2           8745 non-null   float64
 11  cc             8745 non-null   float64
 12  cg             8745 non-null   float64
 13  ci             8745 non-null   float64
 14  p              8745 non-null   float64
 15  p2             8745 non-null   float64
 16  pc             8745 non-null   float64
 17  pg             8745 non-null   float64
 18  pi             8745 non-null   float64
 19  openc          8745 non-null   float64
 20  cgnp           8305 non-null   float64
 21  y              8745 non-null   float64
 22  y2             8745 non-null   float64
 23  rgdpl          8725 non-null   float64
 24  rgdpl2         8725 non-null   float64
 25  rgdpch         8725 non-null   float64
 26  kc             8725 non-null   float64
 27  kg             8725 non-null   float64
 28  ki             8725 non-null   float64
 29  openk          8725 non-null   float64
 30  rgdpeqa        8555 non-null   float64
 31  rgdpwok        8177 non-null   float64
 32  rgdpl2wok      8177 non-null   float64
 33  rgdpl2pe       845 non-null    float64
 34  rgdpl2te       5399 non-null   float64
 35  rgdpl2th       2274 non-null   float64
 36  rgdptt         8745 non-null   float64
dtypes: float64(33), int64(1), object(3)
memory usage: 3.2+ MB
  • dtypes 查看各变量数据类型。

df.dtypes
country           object
isocode           object
year               int64
POP              float64
XRAT             float64
Currency_Unit     object
ppp              float64
tcgdp            float64
cgdp             float64
cgdp2            float64
cda2             float64
cc               float64
cg               float64
ci               float64
p                float64
p2               float64
pc               float64
pg               float64
pi               float64
openc            float64
cgnp             float64
y                float64
y2               float64
rgdpl            float64
rgdpl2           float64
rgdpch           float64
kc               float64
kg               float64
ki               float64
openk            float64
rgdpeqa          float64
rgdpwok          float64
rgdpl2wok        float64
rgdpl2pe         float64
rgdpl2te         float64
rgdpl2th         float64
rgdptt           float64
dtype: object
  • .columns 查看数据框列名(变量名)。

df.columns
Index(['country', 'isocode', 'year', 'POP', 'XRAT', 'Currency_Unit', 'ppp',
       'tcgdp', 'cgdp', 'cgdp2', 'cda2', 'cc', 'cg', 'ci', 'p', 'p2', 'pc',
       'pg', 'pi', 'openc', 'cgnp', 'y', 'y2', 'rgdpl', 'rgdpl2', 'rgdpch',
       'kc', 'kg', 'ki', 'openk', 'rgdpeqa', 'rgdpwok', 'rgdpl2wok',
       'rgdpl2pe', 'rgdpl2te', 'rgdpl2th', 'rgdptt'],
      dtype='object')
  • rename() 函数既可以用于更改行标签,也可以用于列标签。传入一个字典,其中键为当前名称,值为新名称,以更新相应的名称。

例:

  1. 将 year 改为 Year,country 改为 Country:

df_renamed = df.rename(columns={'year':Year, 'country':'Country'})
  1. 将所有列名改为小写:

df_renamed = df.rename(columns=str.lower)
  • .index 查看数据框行名。

df.index
RangeIndex(start=0, stop=11400, step=1)
  • .shape 可以查看 DataFrame 的维度,返回一个 tuple(元组对象),显示数据框的行数和列数。因此,可以用索引分别查看数据框的行数和列数。

#查看数据框行数
print(df.shape[0])

#查看数据框列数
print(df.shape[1])
11400
37