Pandas 数据结构Series、DataFrame分析

用python进行数据分析时经常要用到pandas库,为了以后便于查询,我对pandas库的两个主要数据结构Series和DataFrame的创建和使用方法进行了简单总结。

Series

从概念上说,Series是一个一维数组。但是和普通的python列表不同的是,Series支持索引。普通的python列表只能根据下标来查找特定位置的元素,而Series既可以按下标索引,也可以按照给定的keys进行索引。

1、创建Series

Series的构造函数是 Series(data, index=index, name=name),其中data可以是列表、numpy数组或字典,index表示要对元素进行定位的索引,默认是数字 0,1,..... ,name表示为该Series指定的名字,可以通过Series.name属性获取。

由列表创建Series:

import pandas as pd
import numpy as np

s = pd.Series([1, 2, 3, 4], index=['a', 'b', 'c', 'd'], name='my_series')
print(s)
print(s.data)
print(s.values)
print(s.index)
print(s.name)
a    1
b    2
c    3
d    4
Name: my_series, dtype: int64
<memory at 0x0000000009504E88>
[1 2 3 4]
Index(['a', 'b', 'c', 'd'], dtype='object')
my_series

由numpy数组创建Series:

s1 = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'], name='love')
print(s1)
print(s1.name)
a    0.974985
b    0.885027
c   -0.254667
d   -0.248708
e   -0.446959
Name: love, dtype: float64
love

需要注意的是,用python列表和numpy数组创建Series时,若指定index参数,则index的元素个数必须要与传入的data参数中的元素个数相同!index多于或少于data的元素个数都会报错!

由字典创建Series:

d = {'a': 1, 'b': 2, 'c': 3}
s2 = pd.Series(d, index=['a', 'b'])
s3 = pd.Series(d, index=['a', 'b', 'c', 'd'])
s4 = pd.Series(d)
s5 = pd.Series(d, index=[1, 2])
s6 = pd.Series(d, index=[1, 2, 3, 4])
s7 = pd.Series(d, index=['b', 'c', 'a'])
s8 = pd.Series(2, index=['a', 'b', 'c', 'd'])

print(s2)
print(s3)
print(s4)
print(s5)
print(s6)
print(s7)
print(s8)
a    1
b    2
dtype: int64
a    1.0
b    2.0
c    3.0
d    NaN
dtype: float64
a    1
b    2
c    3
dtype: int64
1   NaN
2   NaN
dtype: float64
1   NaN
2   NaN
3   NaN
4   NaN
dtype: float64
b    2
c    3
a    1
dtype: int64
a    2
b    2
c    2
d    2
dtype: int64

从上面的运行结果可以知道,index的元素个数不一定要与字典中的元素个数相同!当index的元素个数较少时,将会从字典中截取一部分元素;当index元素个数较多时,将会自动保存为NAN。另外,当index中的元素与字典的keys不同时,所有的元素都会变成NAN;当index元素的顺序与keys的顺序不同时,可以改变Series中元素的储存顺序(这个skill可能在某些需要更换元素顺序的场合非常有用);当data参数为一个单一常数或变量时,所有下标都将重复这个变量。

2、Series的数据访问

访问Series既可以像访问list那样运用数组下标(包括列表切片等功能),也可以像字典一样利用keys进行索引,还可以根据某些条件对数据进行索引。

s = pd.Series(np.random.randn(6), index=['a', 'b', 'c', 'd', 'e', 'f'])
print("s[0] = ", s[0])
print("The first 3 numbers: ", s[:3])
print("Access s[0], s[2], s[4] at the same time:", s[[0, 2, 4]])
print("s['b'] = ", s['b'])
print("Access s['b'], s['e'], s['a'] at the same time:", s[['b', 'e', 'a']])
print(s > 0.5)
print(s[s > 0.5])
s[0] =  0.392929141632
The first 3 numbers:  a    0.392929
b    0.603154
c    0.536006
dtype: float64
Access s[0], s[2], s[4] at the same time: a    0.392929
c    0.536006
e   -0.142661
dtype: float64
s['b'] =  0.603154027249
Access s['b'], s['e'], s['a'] at the same time: b    0.603154
e   -0.142661
a    0.392929
dtype: float64
a    False
b     True
c     True
d     True
e    False
f    False
dtype: bool
b    0.603154
c    0.536006
d    1.018407
dtype: float64

注意在同时访问 s[0], s[2], s[4] 的时候,传入的下标是一个列表 s[[0, 2, 4]] 而不是 s[0, 2, 4],这个在按keys进行索引访问时也一样。(s[['b', 'e', 'a']] 而不是 s['b', 'e', 'a']);另外,留意 s > 0.5s[s > 0.5] 的区别。

DataFrame

DataFrame是多个Series数组按列存储后得到的数据结构,相当于一张数据库的表(也可以看成是一张excel表)。在使用DataFrame的时候,我们应该培养自己按列存储和访问数据的直觉。

1、创建DataFrame

创建DataFrame的函数接口为DataFrame(data, index=index, columns=columns)。其中index是行名,columns是列名,data可以是字典、二维数组等。下面分别用字典、二维数组创建DataFrame:

d = {'one': pd.Series([1, 0, 8, 7], index=['a', 'b', 'c', 'd']), 'two': pd.Series(['Jack', 'Lucy', 'Bob'], index=['a', 'b', 'c'])}
arr = [[1, 2, 3], [4, 5, 6]]

df1 = pd.DataFrame(d)
df2 = pd.DataFrame(d, index=[0, 'd', 2, 'b'], columns=['one', '2nd'])
df3 = pd.DataFrame(arr)
df4 = pd.DataFrame(arr, index=['one', 'two'], columns=['a', 'b', 'c'])
df5 = pd.DataFrame(np.random.randn(4, 3), index=['l', 'o', 'v', 'e'], columns=['Jack', 'DXM', 'forever'])

print("df1:")
print(df1)
print("df2:")
print(df2)
print("df3:")
print(df3)
print("df4:")
print(df4)
print("df5:")
print(df5)
df1:
   one   two
a    1  Jack
b    0  Lucy
c    8   Bob
d    7   NaN
df2:
   one  2nd
0  NaN  NaN
d  7.0  NaN
2  NaN  NaN
b  0.0  NaN
df3:
   0  1  2
0  1  2  3
1  4  5  6
df4:
     a  b  c
one  1  2  3
two  4  5  6
df5:
       Jack       DXM   forever
l  0.118821 -0.473873 -0.838605
o -0.974129 -0.803639 -1.474212
v  0.646528 -0.435759 -1.528049
e  1.903572  0.282889 -0.303181

也可以运用concat函数把多个Series或多个小的DataFrame拼接成一个大的DataFrame:

s1 = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])
s2 = pd.Series(np.linspace(12, 78, 5), index=['a', 'b', 'c', 'd', 'e'])
d1 = pd.DataFrame([[4, 5, 6], [7, 8, 9]], index=['one', 'two'], columns=['a', 'b', 'c'])

df6 = pd.concat([s1, s2], axis=1)
df7 = pd.concat([df4, d1], axis=1)
df8 = pd.concat([df4, d1], axis=0)
print("df6:")
print(df6)
print("df7:")
print(df7)
print("df8:")
print(df8)
df6:
   0     1
a  1  12.0
b  2  28.5
c  3  45.0
d  4  61.5
e  5  78.0
df7:
     a  b  c  a  b  c
one  1  2  3  4  5  6
two  4  5  6  7  8  9
df8:
     a  b  c
one  1  2  3
two  4  5  6
one  4  5  6
two  7  8  9

如上述运行结果所示,concat函数的axis参数为0时表示按行合并,为1时表示按列合并,当合并的数据为Series时,则只能按列合并。

2、DataFrame的数据访问

利用DataFrame的index、columns和values分别可以返回行名、列名和一个二维数组:

print("index: ", df5.index)
print("columns: ", df5.columns)
print("values: ")
print(df5.values)
index:  Index(['l', 'o', 'v', 'e'], dtype='object')
columns:  Index(['Jack', 'DXM', 'forever'], dtype='object')
values: 
[[ 0.11882094 -0.47387267 -0.83860489]
 [-0.97412888 -0.80363934 -1.47421162]
 [ 0.64652834 -0.43575855 -1.52804869]
 [ 1.90357243  0.2828892  -0.30318056]]

注意,DataFrame中是按列优先来存储数据的,访问元素时需先以列名获取对应的Series,然后再访问该Series中的某个位置的元素。获取特定某列时若该DataFrame中无列名,则可以按下标来获取列,若该DataFrame中含有列名,则必须按照列名来获取列:

df9 = pd.DataFrame(np.random.randn(6, 2))
print("df9[0]: ")
print(df9[0])
df9.columns = ['Jack', 'DXM']
print("df9[0]:")
print(df9['Jack'])
print("df9[0][2]: ", df9['Jack'][2])
df9[0]: 
0    0.310104
1   -0.541683
2   -0.944970
3    0.619510
4   -0.686613
5   -0.472715
Name: 0, dtype: float64
df9[0]:
0    0.310104
1   -0.541683
2   -0.944970
3    0.619510
4   -0.686613
5   -0.472715
Name: Jack, dtype: float64
df9[0][2]:  -0.944969896368

如果想要获取DataFrame中的某一行,则需要用DataFrame.iloc[]按照下标来访问一行,也可以用DataFrame.loc[]来按keys索引来访问一行:

df9.index = ['a', 'b', 'c', 'd', 'e', 'f']
print("df9's second row: ")
print(df9.iloc[1])
print("df9's third row: ")
print(df9.loc['c'])
df9's second row: 
Jack   -0.541683
DXM     0.208986
Name: b, dtype: float64
df9's third row: 
Jack   -0.944970
DXM     0.004729
Name: c, dtype: float64

还可以利用切片和布尔数组的方式来选取行:

print("df9's second to fifth rows:")
print(df9[1:5])
bool_index = [True, True, False, False, True, False]
print(df9[bool_index])
df9's second to fifth rows:
       Jack       DXM
b -0.541683  0.208986
c -0.944970  0.004729
d  0.619510 -0.300693
e -0.686613 -0.722130
       Jack       DXM
a  0.310104 -0.030625
b -0.541683  0.208986
e -0.686613 -0.722130

对行列进行组合获取数据:

df10 = df8[['b', 'a']].iloc[[3, 1]]
print("df10: ")
print(df10)
df10: 
     b  a
two  8  7
two  5  4

如果需要按照行优先的形式访问DataFrame中的某个数据,可以用DataFrame.iat[]DataFrame.at[]来按照下标或keys索引来访问数据:

print(df8.iat[1, 2])
print(df8.at['one', 'c'])
6
[3 6]

下面的df8.at['one', 'c']返回两个值是因为df8中含有两行数据的名字都为’one’。需要注意的是,如果只是访问DataFrame中某个特定的元素,dataframe.at和dataframe.iat是最快的方式,这种方式与numpy二维数组的访问特定元素方式相同。

参考文献

  1. http://pandas.pydata.org/pandas-docs/stable/10min.html
  2. http://pandas.pydata.org/pandas-docs/stable/cookbook.html#cookbook
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值