import numpy as np
import pandas as pd
obj = pd.Series([4,7,-5,3])
# 通过values属性和index属性分别获得Series对象的值和索引
obj.index
obj.values
obj2 = pd.Series([4, 7, -5, 3], index = ['d','b','a','c'])
obj2
# 与NumPy相比,可以从数据中选择数据的时候使用标签来进行索引
obj2['a']
obj2['d'] = 6
obj2[['c','a','d']]
obj2[obj2 > 0]
obj2 * 2
np.exp(obj2)
从另一个角度考虑Series,可以认为它是一个长度固定且有序的词典,因为它将索引值和数据值按位置配对。在你可能会使用字典的上下文中,可以使用Series
'b' in obj2
# 如果已经有数据在Python字典中,可以使用字典生成一个Series
sdata = {'Ohio':35000, 'Texas':71000, 'Oregon':16000,'Utah':5000}
obj3 = pd.Series(sdata)
obj3
当把字典传递给Series构造函数时,产成的Series的索引将是排序好的字典键。可以将字典键按照所想要的顺序传递给构造函数,从而生产的Series的索引顺序符合你的预期
states = ['California','Ohio','Oregon','Texas']
obj4 = pd.Series(sdata, index = states)
obj4
# 使用isnull和notnull函数来检查缺失数据
pd.isnull(obj4)
pd.notnull(obj4)
# isnull和nutll也是Series的方法
obj4.isnull()
obj4.notnull()
obj3
obj4
obj3 + obj4
# Series对象自身和其索引都有name属性,这个属性与pandas其他重要功能集成在一起
obj4.name = 'population'
obj4.index.name = 'state'
obj4
# Series的索引可以按照位置赋值的方式进行改变
obj
obj.index = ['Bob','Steve','Jeff','Ryan']
obj
有多种方式可以构建DataFrame,其中最常用的方式是利用包含等长度列表或NumPy数组的字典来形成DataFrame
data = {'state':['Ohio','Ohio','Ohio','Nevada','Nevada','Nevada'],
'year':[2000,2001,2002,2001,2002,2003],
'pop':[1.5, 1.7, 3.6, 2.4, 2.9,3.2]}
frame = pd.DataFrame(data)
frame
frame.head()
pd.DataFrame(data, columns=['year','state','pop'])
# 如果传的列不包含在字典中,将会在结果中出现缺失值
frame2 = pd.DataFrame(data, columns = ['year','state','pop','debt'],
index = ['one','two','three','four','five','six'])
frame2
frame2.columns
frame2['state']
frame2.state
frame2['debt'] = 15
frame2
当将列表或数组赋值给一个列时,值的长度必须和DataFrame的长度相匹配。如果将Series赋值给一列时,Series的索引将会按照DataFrame的索引重新排列,并在空缺的地方填充缺失值
val = pd.Series([-1.2, -1.5, -1.7], index = ['two','four','five'])
frame2['debt'] = val
frame2
# del删除列
frame2['eastern'] = frame2.state == 'Ohio'
frame2
del frame2['eastern']
frame2.columns
从DataFrame中选取的列是数据的视图,而不是拷贝。因此,对Series的修改会映射到DataFrame中,如果需要复制,则应当显示的使用Series的copy方法
另一种常用的数据形式是包含字典的嵌套字典
pop = {'Nevada':{2001:2.4,2002:2.9},
'Ohio':{2000:1.5,2001:1.7,2002:3.6}}
pop
# 如果嵌套字典被赋值给DataFrame,pandas会将字典的键作为i列,将内部字典的键作为行索引
frame3 = pd.DataFrame(pop)
frame3
frame3.T
包含Series的字典也可以用于构造DataFrame
pdata = {'Ohio':frame3['Ohio'][:-1],
'Nevada':frame3['Nevada'][:-1]}
pd.DataFrame(pdata)
# 如果DataFrame的索引和列拥有name属性,则这些name属性也会被显示
frame3.index.name = 'year'
frame3.name = 'state'
frame3
# 和Series类似,DataFrame的values属性会将包含在DataFrame中的数据以二维ndarray的形式返回
frame3.values
# 如果DataFrame的列是不同的dtypes,则values的dtype会自动选择适合所有列的类型
frame2.values
pandas中索引对象是用于存储轴标签和其他元数据的,在构造Series或DataFrame时,所使用的任意数组或标签序列都可以在内部转换为索引对象
import pandas as pd
import numpy as np
obj = pd.Series(range(3), index = ['a','b','c'])
index = obj.index
index
index[1:]
#索引对象是不可变的,因此用户是无法修改索引的对象
index[1] = 'd'
# 不可变性使得在多种数据结构中分享索引对象更为安全
labels = pd.Index(np.arange(3))
labels
obj2 = pd.Series([1.5, -2.5, 0], index = labels)
obj2
除了类似数组,索引对象也像一个固定大小的集合。与Python集合不同,pandas索引对象可以包含重复标签。
每个索引都有一些集合逻辑的方法和属性。这些方法和属性解决了关于它所包含的数据的其他常见问题
一些索引对象的方法和属性
append
difference
:计算两个索引的差集
intersection
:计算两个索引的交集
union
: 计算两个索引的并集
isin
: 计算表示每一个值是否在传值容器中的布尔数组
delete
: 将位置i的元素删除,并产生新的索引
drop
: 根据传参删除指定索引值,并产生新的索引
insert
: 在位置i插入元素,并产生新的索引
is_monotonic
: 如果索引序列递增则返回True
is_unique
: 如果索引序列唯一则返回True
unique
obj = pd.Series([4.5, 7.2, -5.3, 3.6], index = ['d','b','a','c'])
obj
obj2 = obj.reindex(['a','b','c','d','e'])
obj2
对于顺序数据,比如时间序列,在重建索引时可能会需要进行插值或填值。method
可选参数允许我们使用诸如ffill
等方法在重建索引时插值,ffill
是前向填充
obj3 = pd.Series(['blue','purple','yellow'], index=[0,2,4])
obj3
obj3.reindex(np.arange(6), method = 'ffill')
obj3
在DataFrame中,reindex
可以改变行索引、列索引,也可以同时改变。当仅传入一个序列时,结果中的行会重建索引
import pandas as pd
import numpy as np
frame = pd.DataFrame(np.arange(9).reshape((3,3)),
index = ['a','b','c'],
columns = ['Ohio','Texas','California'])
frame
frame2 = frame.reindex(['a','b','c','d'])
frame2
# 列可以使用columns关键字重建索引
states = ['Texas','Utah','California']
frame.reindex(columns=states)
# 使用loc进行更为简洁的标签索引
frame.loc[['a','b','c','d'],states]
如果已经拥有索引数组或不含条目的列表,在轴向上删除一个或更多的条目就非常容易,但这样需要一些数据操作和集合逻辑,drop
方法会返回一个含有指示值或轴向上删除值的新对象
obj = pd.Series(np.arange(5), index = ['a','b','c','d','e'])
obj
new_obj = obj.drop('c')
new_obj
obj
obj.drop(['d','c'])
# 在DataFrame中,索引值可以从轴向上删除。
data = pd.DataFrame(np.arange(16).reshape((4,4)),
index = ['Ohio','Colorado','Utah','New York'],
columns = ['one','two','three','four'])
data
# 在调用drop时使用标签序列会根据行标签删除值(轴0)
data.drop(['Colorado','Ohio'])
# 可以通过传递axis=1或axis='columns'来从列中删除值
data.drop('two',axis=1)
data.drop(['two','four'], axis='columns')
# 直接操作原对象
obj.drop('c',inplace=True)
obj
Series的索引(obj[...])与NumPy数组索引的功能类似,只不过Series的索引值可以不仅仅是整数
obj = pd.Series(np.arange(4), index = ['a','b','c','d'])
obj
obj['b']
obj[1]
obj[2:4]
obj[['b','a','d']]
obj[[1,3]]
obj[obj < 2]
obj['b':'c']
obj['b':'c'] = 5
obj
data
data['two']
data.two
data.loc[:, 'two']
data.loc['Ohio']
data.loc['Ohio','two'] #同时选择行和列中的一部分
data[['three','one']]
data[:2]
data[data['three'] > 5]
data < 5
data[data < 5] = 0
data
### 使用轴标签loc和iloc选择数据
data.loc['Colorado', ['two', 'three']]
data.iloc[2]
data.iloc[:, 2]
data.iloc[2, [3,0,1]]
data.iloc[[1,2],[3,0,1]]
data.loc[:'Utah','two']
data.iloc[:,:3][data.three > 5]
不同索引的对象之间的算术行为是pandas提供给一些应用的一项重要特性。当你将对象相加时,如果存在某个索引对不相同,则返回结果的索引将是索引对的并集。对数据库用户来说,这个特性类似于索引标签的自动外链接(outer join)
s1 = pd.Series([7.3, -2.5, 3.4, 1.5], index = ['a','c','d','e'])
s2 = pd.Series([-2.1, 3.6, -1.5, 4, 3.1],
index = ['a','c','e','f','g'])
s1
s2
s1 + s2
df1 = pd.DataFrame(np.arange(9.).reshape((3,3)),
columns = list('bcd'),
index = ['Ohio','Texas','Colorado'])
df2 = pd.DataFrame(np.arange(12.).reshape((4,3)),
columns = list('bde'),
index = ['Utah','Ohio','Texas','Oregon'])
df1
df2
df1 + df2
# 如果将两个行或列完全不同的DataFrame对象相加,结果将全部为空
df1 = pd.DataFrame({'A':[1,2]})
df2 = pd.DataFrame({'B':[3,4]})
df1
df2
df1 - df2
df1 = pd.DataFrame(np.arange(12.).reshape((3,4)),
columns = list('abcd'))
df2 = pd.DataFrame(np.arange(20.).reshape((4,5)),
columns = list('abcde'))
df2.loc[1,'b'] = np.nan
df1
df2
# 将这些df添加到一起会导致在一些不重叠的位置出现NA
df1 + df2
df1.add(df2, fill_value=0)
df1.reindex(columns = df2.columns, fill_value = 0)
算术方法
add, radd
sub, rsub
div, rdiv
floordiv, rfloordiv
mul, rmul
pow, rpow
frame = pd.DataFrame(np.arange(12.).reshape((4,3)),
columns=list('bde'),
index=['Utah','Ohio','Texas','Oregon'])
series = frame.iloc[0]
frame
series
frame - series
series2 = pd.Series(range(3), index = ['b','e','f'])
frame + series2
frame = pd.DataFrame(np.random.randn(4,3),
columns=list('bde'),
index=['Utah','Ohio','Texas','Oregon'])
frame
np.abs(frame)
另一个常用的操作是用apply
将函数应用到一行或一列的一维数组上。
f = lambda x: x.max() - x.min()
frame.apply(f)
frame.apply(f, axis = 'columns')
# 传递给apply的函数并不一定要返回一个标量值,也可以返回带有多个值的Series
def f(x):
return pd.Series([x.min(), x.max()], index = ['min','max'])
frame.apply(f)
逐元素的Python函数也可以使用,假设想要根据frame中的每个浮点数计算一个格式化字符串,可以使用applymap
方法
format = lambda x: '%.2f' %x
frame.applymap(format)
# 使用applymap作为函数名是因为Series有map方法,可以将逐元素函数应用到Series上
frame['e'].map(format)
obj = pd.Series(range(4), index = ['d','a','b','c'])
obj.sort_index()
# 在DataFrame中,可以在各个轴上按索引排序
frame = pd.DataFrame(np.arange(8).reshape((2,4)),
index = ['three','one'],
columns = ['d','a','b','c'])
frame.sort_index()
frame.sort_index(axis = 1, ascending = False)
# 如果要对Series的值进行排序,使用sort_values方法:
obj = pd.Series([4,7,-3,2])
obj.sort_values()
# 当对DataFrame排序时,可以使用一列或多列作为排序键:
frame = pd.DataFrame({'b':[4,7,-3,2],'a':[0,1,0,1]})
frame
frame.sort_values(by = 'b')
frame.sort_values(by = ['a','b'])
# Series和DataFrame的rank方法实现排名,默认情况下rank通过将平均排名分配到每个组来打破平级关系
obj = pd.Series([7, -5, 7, 4, 2, 0,4])
obj.rank()
# 排名也可以根据他们在数据中的观察顺序进行分配
obj.rank(method= 'first')
# 按降序排名,将值分配给组中的最大排名
obj.rank(ascending = False, method='max')
frame = pd.DataFrame({'b':[4.3,7,-3,2],'a':[0,1,0,1],'c':[-2,5,8,-2.5]})
frame
frame.rank(axis='columns')
排名中平级关系打破方法
average
: 默认,在每个组中分配平均排名
min
: 对整个组使用最小排名
max
: 对整个组使用最大排名
first
: 按照值在数据中出现的次序分配排名
dense
: 类似于method='min'
,但组间排名总是增加1,而不是一个组中的相等元素的数量
df = pd.DataFrame([[1.4,np.nan],[7.1,-4.5],
[np.nan, np.nan],[0.75, -1.3]],
index=['a','b','c','d'],
columns=['one','two'])
df
df.sum()
df.sum(axis=1)
df.sum(axis="columns")
# 除非整个切片(在本例中是行或列)都是NA,否则NA值是被自动排除的。可以通过禁用skipna来实现不排除NA值
df.mean(axis="columns",skipna=False)
# idxmin和idxmax,返回的是间接统计信息,比如最小值或最大值所在的索引标签
df.idxmax()
df.idxmin()
df.cumsum()
df.describe()
# 对于非数值型数据,describe产生另一种汇总统计
obj = pd.Series(['a','a','b','c'] * 4)
obj.describe()
描述性统计和汇总统计
count
: 非NA值的个数
describe
: 计算Series或DataFrame各列的汇总统计集合
min, max
argmin, argmax
idxmin, idxmax
quantile
: 计算样本从0到1间的分位数
sum
mean
median
mad
: 平均值的平均绝对偏差
prod
: 所有值的积
var
: 值的样本方差
std
: 标准差
skew
: 偏度
kurt
: 峰度
cumsum
cummin, cummax
cumprod
diff
pct_change
: 计算百分比
obj = pd.Series(['c','a','d','a','a','b','b','c','c'])
uniques = obj.unique()
uniques
唯一值并不一定按照排序好的顺序返回,但是如果需要的话可以进行排序(uniques.sort()
)。相应的,value_counts()
计算Series包含的值的个数
obj.value_counts()
# value_counts也是有效的pandas顶层方法,可以用于任意数组或序列
# 其返回一个Series,索引是唯一值序列,值是计数个数,按照个数降序排序
pd.value_counts(obj.values, sort=False)
# is执行向量化的成员属性检查,还可以将数据集以Series或DataFrame一列的形式过滤为数据集的值子集
obj
mask=obj.isin(['b','c'])
mask
obj[mask]
与isin
相关的Index.get_indexer
方法,可以提供一个索引数组,这个索引数组可以将可能非唯一值数组转换为另一个唯一值数组
to_match = pd.Series(['c','a','b','b','c','a'])
unique_vals = pd.Series(['c','b','a'])
to_match
pd.Index(unique_vals).get_indexer(to_match)
唯一值、计数和集合成员属性方法
isin
match
: 计算数组中每个值的整数索引,形成一个唯一值数组。有助于数据对齐和join类型的操作
unique
value_counts
data = pd.DataFrame({'Qu1':[1,3,4,3,4],
'Qu2':[2,3,1,2,3],
'Qu3':[1,5,2,4,4]})
data
result = data.apply(pd.value_counts).fillna(0)
# 结果中行标签是所有列中出现的不同值,数值则是这些不同值在每个列中出现的次数
result