Python 学习笔记之—— Pandas 库

2019-12-09  本文已影响0人  seniusen
import numpy as np
import pandas as pd

1. 基本的数据结构

1.1 Series

Series 是一维的标记数组,可以容纳任意数据类型,比如整数、字符串、浮点数或者 Python 对象,轴标记则称之为索引(index),其可以通过 s = pd.Series(data, index=index) 来简单地进行创建。

这里,data 可以是一个字典、Numpy 数组或者是一个标量,传进去的 index 是一个轴标记的列表。

# 通过数组来创建
data = np.random.rand(5)
s = pd.Series(data)
print(s)
index = ['a', 'b', 'c', 'd', 'e']
s = pd.Series(data, index=index)
print(s)
index = ['a', 'a', 'c', 'd', 'e']
pd.Series(data, index=index)
0    0.161391
1    0.399114
2    0.239517
3    0.174435
4    0.509980
dtype: float64

a    0.161391
b    0.399114
c    0.239517
d    0.174435
e    0.509980
dtype: float64

a    0.161391
a    0.399114
c    0.239517
d    0.174435
e    0.509980
dtype: float64

如果不指定 index,则索引默认为 [0, 1...n-1]。而且索引并不一定必须是唯一的,只不过当进行一个不支持重复索引的操作时,会抛出一个异常。

# 通过字典来创建
d = {'b': 1, 'a': 0, 'c': 2}
pd.Series(d)
pd.Series(d, index=['a', 'b', 'c', 'd'])
a    0.0
b    1.0
c    2.0
d    NaN
dtype: float64

如果不指定 index,则索引默认为字典的键,如果指定了的话,我们就从字典中取出索引对应的数据,缺失的值则默认标记为 NaN

# 通过标量来创建
index = ['a', 'b', 'c', 'd', 'e']
pd.Series(5, index)
a    5
b    5
c    5
d    5
e    5
dtype: int64

如果通过标量来创建,那么必须指定 index,数值会重复来匹配索引的长度。

print(s[0])
print(s[1:-1])
print(s[s > 0.40])
s.dtype
0.1613914172020462

b    0.399114
c    0.239517
d    0.174435
dtype: float64

e    0.50998
dtype: float64

dtype('float64')

Series 是类数组的,支持一些数组的操作,比如你可以通过切片来访问,也可以查看它的数据类型等。

print(s['a'])
s['e'] = 12
print(s)
'e' in s
0.1613914172020462

a     0.161391
b     0.399114
c     0.239517
d     0.174435
e    12.000000
dtype: float64

True

Series 是类字典的,你可以通过索引得到它对应的值,也可以改变数据等。

print(s * 2)
print(np.exp(s))
s[1:] + s[:-1]
a     0.322783
b     0.798228
c     0.479035
d     0.348871
e    24.000000
dtype: float64

a         1.175145
b         1.490504
c         1.270636
d         1.190574
e    162754.791419
dtype: float64

a         NaN
b    0.798228
c    0.479035
d    0.348871
e         NaN
dtype: float64

Series 可以像数组一样支持向量化的操作,只不过这里它们会根据索引自动对齐,而不用我们去考虑,在其中一个 Series 中缺失的值会标记为 NaN

s = pd.Series(np.random.randn(5), name='something')
print(s)
s = s.rename('another thing')
s.name
0    2.088204
1   -0.251980
2    0.191687
3   -0.702280
4    2.679027
Name: something, dtype: float64


'another thing'

Series 还可以有一个名称的属性,我们也可以随时对其进行更改。

1.2 DataFrame

DataFrame 是二维标记的数据结构,它的列可以是不同的类型,可以将它看作是一个电子表格、SQL 表或者是包含 Series 对象的字典。DataFrame 接受很多种不同的输入:包含一维数组、列表、字典或者 Series 的字典;二维数组;另一个 DataFrame 等。同时,也可以选择性地传递索引(index)——行标记和列(columns)——列标记参数。

# 从包含 Series 的字典创建
d = {'one': pd.Series([1., 2., 3.], index=['a', 'b', 'c']),
     'two': pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
print(df)
df1 = pd.DataFrame(d, index=['d', 'b', 'a'])
print(df1)
df2 = pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three'])
print(df2)
   one  two
a  1.0  1.0
b  2.0  2.0
c  3.0  3.0
d  NaN  4.0

   one  two
d  NaN  4.0
b  2.0  2.0
a  1.0  1.0

   two three
d  4.0   NaN
b  2.0   NaN
a  1.0   NaN

结果中的索引将会是不同 Series 的并集,同时我们也可以分别指定索引和列。

# 从数组或者列表创建
d = {'one': [1., 2., 3., 4.],
     'two': [4., 3., 2., 1.]}
print(pd.DataFrame(d))
print(pd.DataFrame(d, index=['a', 'b', 'c', 'd']))
   one  two
0  1.0  4.0
1  2.0  3.0
2  3.0  2.0
3  4.0  1.0

   one  two
a  1.0  4.0
b  2.0  3.0
c  3.0  2.0
d  4.0  1.0

这时候数组的大小必须相同,如果传递了索引的话,那么索引的长度必须和数组大小一致。

print(df['one'])
df['three'] = df['one'] * df['two']
df['flag'] = df['one'] > 2
print(df)
del df['two']
three = df.pop('three')
print(df)
df['foo'] = 'bar'
df['one_trunc'] = df['one'][:2]
print(df)
a    1.0
b    2.0
c    3.0
d    NaN
Name: one, dtype: float64

   one  two  three   flag
a  1.0  1.0    1.0  False
b  2.0  2.0    4.0  False
c  3.0  3.0    9.0   True
d  NaN  4.0    NaN  False

   one   flag
a  1.0  False
b  2.0  False
c  3.0   True
d  NaN  False

   one   flag  foo  one_trunc
a  1.0  False  bar        1.0
b  2.0  False  bar        2.0
c  3.0   True  bar        NaN
d  NaN  False  bar        NaN

我们可以把 DataFrame 看作是一个字典来对它的列执行取出、设置和删除操作。当插入一个标量的时候,这个值会填满整列。

2. 10 分钟入门

2.1 查看数据

dates = pd.date_range('20130101', periods=6)
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
print(df)
                   A         B         C         D
2013-01-01 -0.894992  1.827753 -0.525777  0.187190
2013-01-02 -0.844346  1.267231 -0.645592  0.919141
2013-01-03  0.796179 -1.399534  0.686902  1.388934
2013-01-04 -0.579014 -0.409705 -0.386375  1.032558
2013-01-05 -1.676227  1.101409 -1.348775 -0.177341
2013-01-06  0.024847 -0.205337  1.801102  0.265285
print(df.head())
print(df.tail(3))
   one  two
a  1.0  1.0
b  2.0  2.0
c  3.0  3.0
d  NaN  4.0

   one  two
b  2.0  2.0
c  3.0  3.0
d  NaN  4.0
print(df.index)
df.columns
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
               '2013-01-05', '2013-01-06'],
              dtype='datetime64[ns]', freq='D')

Index(['A', 'B', 'C', 'D'], dtype='object')
# 快速显示数据的统计特性
print(df.describe())
       one       two
count  3.0  4.000000
mean   2.0  2.500000
std    1.0  1.290994
min    1.0  1.000000
25%    1.5  1.750000
50%    2.0  2.500000
75%    2.5  3.250000
max    3.0  4.000000
# 对列索引降序排列
df = df.sort_index(axis=1, ascending=False)
print(df)
   two  one
a  1.0  1.0
b  2.0  2.0
c  3.0  3.0
d  4.0  NaN
# 对 B 列的数值排序
df = df.sort_values(by='B')
print(df)
                   A         B         C         D
2013-01-03  0.796179 -1.399534  0.686902  1.388934
2013-01-04 -0.579014 -0.409705 -0.386375  1.032558
2013-01-06  0.024847 -0.205337  1.801102  0.265285
2013-01-05 -1.676227  1.101409 -1.348775 -0.177341
2013-01-02 -0.844346  1.267231 -0.645592  0.919141
2013-01-01 -0.894992  1.827753 -0.525777  0.187190

2.2 按照标记选择

print(df.loc[dates[0:1]])
                   A         B         C        D
2013-01-01 -0.894992  1.827753 -0.525777  0.18719
print(df.loc['20130102':'20130104', ['A', 'B']])
                   A         B
2013-01-03  0.796179 -1.399534
2013-01-04 -0.579014 -0.409705
2013-01-02 -0.844346  1.267231
df.loc[dates[0], 'A']
0.8144031024228705

2.3 按照位置选择

df.iloc[3]
A    0.091327
B   -0.570903
C    1.855473
D    1.807595
Name: 2013-01-04 00:00:00, dtype: float64
print(df.iloc[3:5, 0:2])
                   A         B
2013-01-05 -1.676227  1.101409
2013-01-02 -0.844346  1.267231
print(df.iloc[1, 1])
-0.4097050352704689

2.4 布尔索引

print(df[df.A > 0])
                   A         B         C         D
2013-01-03  0.796179 -1.399534  0.686902  1.388934
2013-01-06  0.024847 -0.205337  1.801102  0.265285
print(df[df > 0])
                   A         B         C         D
2013-01-03  0.796179       NaN  0.686902  1.388934
2013-01-04       NaN       NaN       NaN  1.032558
2013-01-06  0.024847       NaN  1.801102  0.265285
2013-01-05       NaN  1.101409       NaN       NaN
2013-01-02       NaN  1.267231       NaN  0.919141
2013-01-01       NaN  1.827753       NaN  0.187190

2.5 缺失数据

df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ['E'])
df1.loc[dates[0]:dates[1], 'E'] = 1
print(df1)
                   A         B         C         D    E
2013-01-01 -0.894992  1.827753 -0.525777  0.187190  1.0
2013-01-02 -0.844346  1.267231 -0.645592  0.919141  1.0
2013-01-03  0.796179 -1.399534  0.686902  1.388934  NaN
2013-01-04 -0.579014 -0.409705 -0.386375  1.032558  NaN
print(df1.dropna(how='any')) # 删除任意包含 NaN 的行
                   A         B         C         D    E
2013-01-01 -0.894992  1.827753 -0.525777  0.187190  1.0
2013-01-02 -0.844346  1.267231 -0.645592  0.919141  1.0
print(df1.fillna(value=5)) # 填充缺失数据
                   A         B         C         D    E
2013-01-01 -0.894992  1.827753 -0.525777  0.187190  1.0
2013-01-02 -0.844346  1.267231 -0.645592  0.919141  1.0
2013-01-03  0.796179 -1.399534  0.686902  1.388934  5.0
2013-01-04 -0.579014 -0.409705 -0.386375  1.032558  5.0
print(pd.isna(df1))
                A      B      C      D      E
2013-01-01  False  False  False  False  False
2013-01-02  False  False  False  False  False
2013-01-03  False  False  False  False   True
2013-01-04  False  False  False  False   True

2.6 操作

df.mean()
A    0.493828
B   -0.555683
C    1.068909
D   -0.675655
dtype: float64
df.mean(1)
2013-01-01    0.725959
2013-01-02    0.317094
2013-01-03   -0.834986
2013-01-04    0.795873
2013-01-05   -0.076024
2013-01-06   -0.430818
Freq: D, dtype: float64
df.apply(lambda x: x.max() - x.min())
A    2.283890
B    2.470330
C    2.813372
D    3.389214
dtype: float64
s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca', np.nan, 'CABA', 'dog', 'cat'])
s.str.lower()
0       a
1       b
2       c
3    aaba
4    baca
5     NaN
6    caba
7     dog
8     cat
dtype: object
df2 = pd.DataFrame({'one':['A', 'B'], 'two':['c', 'd']})
print(df2)
df2['one'] = df2['one'].apply(str.lower)
df2['two'] = df2['two'].apply(str.upper)
print(df2)
  one two
0   A   c
1   B   d
  one two
0   a   C
1   b   D

2.7 合并

df = pd.DataFrame(np.random.randn(5, 4))
print(df)
          0         1         2         3
0 -0.811113 -0.087698 -1.980786  0.129838
1 -0.083298 -0.803188  0.012908 -1.052246
2  0.534317  0.411549  1.638672 -0.182032
3  0.002322  0.857579  1.716546 -0.531305
4  0.210017  0.156584 -0.487976 -1.230442
pieces = [df[:2], df[2:4], df[4:]]
print(pd.concat(pieces))
          0         1         2         3
0 -0.811113 -0.087698 -1.980786  0.129838
1 -0.083298 -0.803188  0.012908 -1.052246
2  0.534317  0.411549  1.638672 -0.182032
3  0.002322  0.857579  1.716546 -0.531305
4  0.210017  0.156584 -0.487976 -1.230442
left = pd.DataFrame({'key': ['val', 'foo', 'bar'], 'lval': [0, 1, 2]})
right = pd.DataFrame({'key': ['foo', 'foo', 'bar', 'end'], 'rval': [4, 3, 5, 6]})
print(left)
print(right)
   key  lval
0  val     0
1  foo     1
2  bar     2

   key  rval
0  foo     4
1  foo     3
2  bar     5
3  end     6
print(pd.merge(left, right, on='key')) # 基于 key 这一列合并
   key  lval  rval
0  foo     1     4
1  foo     1     3
2  bar     2     5
print(pd.merge(left, right, how='inner')) # 内连接也就是基于键的交集
   key  lval  rval
0  foo     1     4
1  foo     1     3
2  bar     2     5
print(pd.merge(left, right, how='left')) # 左连接以第一个 DataFrame 为主
   key  lval  rval
0  val     0   NaN
1  foo     1   4.0
2  foo     1   3.0
3  bar     2   5.0
print(pd.merge(left, right, how='right')) # 右连接以第二个 DataFrame 为主
   key  lval  rval
0  foo   1.0     4
1  foo   1.0     3
2  bar   2.0     5
3  end   NaN     6
print(pd.merge(left, right, how='outer')) # 外连接也就是基于键的并集
   key  lval  rval
0  val   0.0   NaN
1  foo   1.0   4.0
2  foo   1.0   3.0
3  bar   2.0   5.0
4  end   NaN   6.0

3. 一个小例子

name = ['张飞', '关羽', '黄忠', '赵云', '典韦', '典韦']
chinese = [66, 95, 95, 90, 80, 80]
english = [65, 85, 92, 88, 90, 90]
math = [np.nan, 98, 96, 77, 90, 90]
dic = dict({'语文':chinese, '英语':english, '数学':math})
score = pd.DataFrame(dic, index=name)
print(score)
      数学  英语  语文
张飞   NaN  65  66
关羽  98.0  85  95
黄忠  96.0  92  95
赵云  77.0  88  90
典韦  90.0  90  80
典韦  90.0  90  80
score = score.drop_duplicates()
score = score.fillna(score['数学'].mean())
print(score)
      数学  英语  语文
张飞  90.2  65  66
关羽  98.0  85  95
黄忠  96.0  92  95
赵云  77.0  88  90
典韦  90.0  90  80
def cal_total(df):
    df['总分'] = df['英语'] + df['英语'] + df['英语']
    return df

#print(cal_total(score))
score = score.apply(cal_total, axis=1)
print(score)
      数学    英语    语文     总分
张飞  90.2  65.0  66.0  195.0
关羽  98.0  85.0  95.0  255.0
黄忠  96.0  92.0  95.0  276.0
赵云  77.0  88.0  90.0  264.0
典韦  90.0  90.0  80.0  270.0
score = score.sort_values(by='总分')
print(score)
      数学    英语    语文     总分
张飞  90.2  65.0  66.0  195.0
关羽  98.0  85.0  95.0  255.0
赵云  77.0  88.0  90.0  264.0
典韦  90.0  90.0  80.0  270.0
黄忠  96.0  92.0  95.0  276.0
上一篇下一篇

猜你喜欢

热点阅读