分享

Python 数据分析——Pandas 数值运算函数

 禁忌石 2023-08-06 发布于浙江
Python 数据分析——Pandas 数值运算函数

Series和DataFrame对象都支持NumPy的数组接口,因此可以直接使用NumPy提供的ufunc函数对它们进行运算。此外它们还提供各种运算方法,例如max()、min()、mean()、std()等。这些函数都有如下三个常用参数:

·axis:指定运算对应的轴。

·level:指定运算对应的索引级别。

·skipna:运算是否自动跳过NaN。

Python 数据分析——Pandas 数值运算函数

下面分别计算每列的平均值、每行的平均值以及行索引的第1级别Contour中每个等高线对应的平均值:

Python 数据分析——Pandas 数值运算函数

除了支持加减乘除等运算符之外,Pandas还提供了add()、sub()、mul()、div()、mod()等与二元运算符对应的函数。这些函数可以通过axis、level和fill_value等参数控制其运算行为。在下面的例子中,对不同的等高线的Ca的值乘上不同的系数,fill_value参数为1表示对于不存在的值或NaN使用默认值1。因此结果中,所有Depression对应的值为原来的0.9倍,Slope对应的值为原来的1.2倍,而Top对应的值保持不变。

s = pd.Series(dict(Depression=0.9, Slope=1.2))df_soil.Ca.mul(s, level=1, fill_value=1)Depth Contour 0-10 Depression 9.6Slope 15Top 1310-30 Depression 6.8Slope 11Top 10dtype: float64

Pandas还提供了rolling_*()函数来对序列中相邻的N个元素进行移动窗口运算。例如可以使用rolling_median()实现中值滤波,使用rolling_mean()计算移动平均。图1显示了使用这两个函数对带脉冲噪声的正弦波进行处理的结果。它们的第二个参数为窗口包含的元素个数,而center参数为True表示移动窗口以当前元素为中心。

Python 数据分析——Pandas 数值运算函数

图1 中值滤波和移动平均

由于rolling_median()采用了更高效的算法,因此当窗口很大时它的运算速度比SciPy章节中介绍过的signal.order_filter()更快。

t = np.linspace(0, 10, 400)x = np.sin(0.5*2*np.pi*t)x[np.random.randint(0, len(t), 40)] += np.random.normal(0, 0.3, 40)s = pd.Series(x, index=t)s_mean = pd.rolling_mean(s, 5, center=True)s_median = pd.rolling_median(s, 5, center=True)

expanding_*()函数对序列进行扩展窗口运算,例如expanding_max()返回到每个元素为止的历史最大值。图2显示了expanding_max()、expanding_mean()和expanding_min()的运算结果。

请读者思考如何使用NumPy提供的ufunc函数计算图2中的三条曲线。

np.random.seed(42)x = np.cumsum(np.random.randn(400))x_max = pd.expanding_max(x)x_min = pd.expanding_min(x)x_mean = pd.expanding_mean(x)
Python 数据分析——Pandas 数值运算函数

图2 用expanding_*计算历史最大值、平均值、最小值

字符串处理

Series对象提供了大量的字符串处理方法,由于数量众多,因此Pandas使用了一个类似名称空间的对象str来包装这些字符串相关的方法。例如下面的程序调用str.upper()将序列中的所有字母都转换为大写:

s_abc = pd.Series(['a', 'b', 'c'])print s_abc.str.upper()0    A1    B2    Cdtype: object

Python中包含两种字符串:字节字符串和Unicode字符串。通过str.decode()可以将字节字符串按照指定的编码解码为Unicode字符串。例如在UTF-8编码中,一个汉字占用三个字符,因此下面的s_utf8中的字符串长度分别为6、9、12。当调用str.decode()将其转换为Unicode字符串的序列之后,其各个元素的长度为实际的文字个数。str.encode()可以把Unicode字符串按照指定的编码转换为字节字符串,在常用的汉字编码GB2312中,一个汉字占用两个字节,因此s_gb2312的元素长度分别为4、6、8。

Python 数据分析——Pandas 数值运算函数

无论Series对象包含哪种字符串对象,其dtype属性都是object,因此无法根据它判断字符串类型。在处理文本数据时,需要格外注意字符串的类型。

可以对str使用整数或切片下标,相当于对Series对象中的每个元素进行下标运算,例如:

print s_unicode.str[:2]0 北京1 北京2 北京dtype: object

字符串序列与字符串一样,支持加法和乘法运算,例如:

print s_unicode + u'-' + s_abc * 20    北京-aa1     北京市-bb2  北京地区-ccdtype: object

也可以使用str.cat()连接两个字符串序列的对应元素:

print s_unicode.str.cat(s_abc, sep='-')0 北京-a1 北京市-b2 北京地区-cdtype: object

调用astype()方法可以对Series对象中的所有元素进行类型转换,例如下面将整数序列转换为字符串序列:

print s_unicode.str.len().astype(unicode)0    21    32    4dtype: object

str中的有些方法可以对元素类型为列表的Series对象进行处理,例如下面调用str.split()将s中的每个字符串使用字符'|'分隔,所得到的结果s_list的元素类型为列表。然后调用它的str.join()方法以逗号连接每个列表中的元素:

Python 数据分析——Pandas 数值运算函数

对字符串序列进行处理时,经常会得到元素类型为列表的序列。Pandas没有提供处理这种序列的方法,不过可以通过str[]获取其中的元素:

s_list.str[1]0 bc1 xyzdtype: object

或者先将其转换为嵌套列表,然后再转换为DataFrame对象:

print pd.DataFrame(s_list.tolist(), columns=['A', 'B', 'C'])A    B   C0  a   bc  de1  x  xyz  yz

Pandas还提供了一些正则表达式相关的方法。例如使用其中的str.extract()可以从字符串序列中抽取出需要的部分,得到DataFrame对象。下面的例子中,df_extract1对应的正则表达式包含三个未命名的组,因此其结果包含三个自动命名的列。而df_extract2对应的正则表达式包含两个命名组,因此其列名为组名。

df_extract1 = s.str.extract(r'(\w+)\|(\w+)\|(\w+)')df_extract2 = s.str.extract(r'(?P<A>\w+)\|(?P<B>\w+)|')df_extract1 df_extract2------------- -----------0 1 2 A B 0 a bc de 0 a bc 1 x xyz yz 1 x xyz

在处理数据时,经常会遇到这种以特定分隔符分隔关键字的数据,例如下面的数据可以用于表示有向图,其第一列为边的起点、第二列为以'|'分隔的多个终点。下面使用read_csv()读入该数据,得到一个两列的DataFrame对象:

import iotext = '''A, B|C|DB, E|FC, AD, B|C'''df = pd.read_csv(io.BytesIO(text), skipinitialspace=True, header=None)print df0      10  A  B|C|D1  B    E|F2  C      A

可以使用下面的程序将上述数据转换为每行对应一条边的数据。❶nodes是一个元素类型为列表的Series对象。❷调用NumPy数组的repeat()方法将第一列数据重复相应的次数。由于repeat()只能接受32位整数,而str.len()返回的是64位整数,因此还需要进行类型转换。❸将嵌套列表平坦化,转换为一维数组。

Python 数据分析——Pandas 数值运算函数
Python 数据分析——Pandas 数值运算函数

还可以把原始数据的第二列看作第一列数据的标签,为了后续的数据分析,通常使用str.get_dummies()将这种数据转换为布尔DataFrame对象,每一列与一个标签对应,元素值为1表示对应的行包含对应的标签:

Python 数据分析——Pandas 数值运算函数

当字符串操作很难用向量化的字符串方法表示时,可以使用map()函数,将针对每个元素运算的函数运用到整个序列之上:

df[1].map(lambda s:max(s.split('|')))0 D1 F2 A3 CName: 1, dtype: object

当用字符串序列表示分类信息时,其中会有大量相同的字符串,将其转换为分类(Category)序列可以节省内存、提高运算效率。例如在下面的df_soil对象中,Contour、Depth和Gp列都是表示分类的数据,因此有许多重复的字符串。

df_soil = pd.read_csv('Soils.csv', usecols=[2, 3, 4, 6])print df_soil.dtypesContour     objectDepth       objectGp          objectpH         float64dtype: object

下面循环调用astype('category')将这三列转换为分类列:

for col in ['Contour', 'Depth', 'Gp']:df_soil[col] = df_soil[col].astype('category')print df_soil.dtypesContour categoryDepth categoryGp categorypH float64dtype: object

与名称空间对象str类似,元素类型为category的Series对象提供了名称空间对象cat,其中保存了与分类序列相关的各种属性和方法。例如cat.categories是保存所有分类的Index对象:

Gp = df_soil.Gpprint Gp.cat.categoriesIndex([u'D0', u'D1', u'D3', u'D6', u'S0', u'S1', u'S3', u'S6', u'T0', u'T1',u'T3', u'T6'],dtype='object')

而cat.codes则是保存下标的整数序列,元素类型为int8,因此一个元素用一个字节表示。

Python 数据分析——Pandas 数值运算函数

分类数据有无序和有序两种,无序分类中的不同分类无法比较大小,例如性别;有序分类则可以比较大小,例如年龄段。上面创建的三个分类列为无序分类,可以通过cat.as_ordered()和cat.as_unordered()在这两种分类之间相互转换。下面的程序通过cat.as_ordred()将深度分类列转换为有序分类,注意最后一行分类名之间使用“<”连接,表示是有序分类。

depth = df_soil.Depthdepth.cat.as_ordered().head() ------------------------------------------------------0 0-10 1 0-10 2 0-10 3 0-10 4 10-30 dtype: category Categories (4, object): [0-10 10-30 30-60 60-90]

如果需要自定义分类中的顺序,可以使用cat.reorder_categories()指定分类的顺序:

contour = df_soil.Contourcategories = ['Top', 'Slope', 'Depression']contour.cat.reorder_categories(categories, ordered=True).head()---------------------------------------------------------------0    Top                                                       1    Top                                                       2    Top                                                       3    Top                                                       4    Top                                                       dtype: category                                                Categories (3, object): [Top < Slope < Depression]     

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多