关于遍历Pandas的几种方法

前言

           最近要做一个数据挖掘的比赛,又用到了Pandas的遍历,所以想系统的整理下pandas的东西。

           Pandas是python的一个数据分析包,提供了大量的快速便捷处理数据的函数和方法。其中Pandas定义了SeriesDataFrame两种数据类型,这使数据操作变得更简单。Series 是一种一维的数据结构,类似于将列表数据值与索引值相结合。DataFrame 是一种二维的数据结构,接近于电子表格或者mysql数据库的形式。(如下图:)

         在数据分析中不可避免的涉及到对数据的遍历查询和处理,比如我们需要将dataframe两列数据两两相除,并将结果存储于一个新的列表中。

 

方法1:for..in循环迭代方式

         for语句是Python内置的迭代器工具,用于从可迭代容器对象(如列表、元组、字典、集合、文件等)中逐个读取元素,直到容器中没有更多元素为止,工具和对象之间只要遵循可迭代协议即可进行迭代操作。
         具体的迭代的过程:可迭代对象通过__iter__方法返回迭代器,迭代器具有__next__方法,for循环不断地调用__next__方法,每次按序返回迭代器中的一个值,直到迭代到最后,没有更多元素时抛出异常StopIteration(python自动处理异常)。迭代的优点是无需把所有元素一次加载到内存中,可以在调用next方法时逐个返回元素,避免出现内存空间不够的情况。          

# -*- coding: utf-8 -*-
"""
Created on Sun Nov  4 15:33:07 2018

@author: wenhuatang
"""

x = [1, 2, 3]
iter = x.__iter__()
print(next(iter))
print(next(iter))
print(next(iter))



result:
1
2
3

 

假如你要使用for..in的方式实现将dataframe两列数据两两相除,并将结果存储于一个新的列表中:

# -*- coding: utf-8 -*-
"""
Created on Sun Nov  4 15:33:07 2018

@author: wenhuatang
"""

def myfunction(df):
    res_list = []
    for i in range(0,len(df)):
        res_list.append(df.iloc[i]['first']/df.iloc[i][‘second'])
    return disftance_list

       惊喜的事情来啦,如果你有特殊需求,你也可根据迭代器协议自实现相同功能的迭代器(自带iter方法和next方法)应用在for循环中,代码如下:

# -*- coding: utf-8 -*-
"""
Created on Sun Nov  4 15:33:07 2018

@author: wenhuatang
"""
class TangRange():
    def __init__(self, num):
        self.i = 0
        self.num = num
    def __iter__(self):
        return self
    def __next__(self):
        if self.i < self.num:
            i = self.i
            self.i += 2
            return i
        else:
            raise StopIteration()
            
for i in TangRange(10):
    print(i)

result:
0
2
4
6
8

 

方法2:iterrows()生成器方式

       iterrows()是对dataframe行进行迭代的一个生成器,它返回每行的索引及包含行本身的对象。所谓生成器其实是一种特殊的迭代器,内部支持了迭代器协议。Python中提供生成器函数生成器表达式两种方式实现生成器,每次请求返回一个结果,不需要一次性构建一个结果列表,节省了内存空间。

a 生成器函数:编写为常规的def语句,但是使用yield语句一次返回一个结果,在每个结果之间挂起和继续它们的状态。

# -*- coding: utf-8 -*-
"""
Created on Sun Nov  4 15:33:07 2018

@author: wenhuatang
"""
def gensquares(N):
    for i in range(N):
        yield i**2
print(gensquares(5))

for i in gensquares(5):
    print(i) 

result:
<generator object gensquares at 0x000002A38971E9A8>
0
1
4
9
16

b.类似列表解析,按需产生结果的一个对象。

# -*- coding: utf-8 -*-
"""
Created on Sun Nov  4 15:33:07 2018

@author: wenhuatang
"""
print (x**2 for x in range(5))
print (list(x**2 for x in range(5)))

result:
<generator object <genexpr> at 0x000002A38971E9A8>
[0, 1, 4, 9, 16]

使用iterrows()的方式实现将dataframe两列数据两两相除,并将结果存储于一个新的列表中:

# -*- coding: utf-8 -*-
"""
Created on Sun Nov  4 15:33:07 2018

@author: wenhuatang
"""


def haversine_looping(df):
    disftance_list = []
    for index,row in df.iterrows():
        disftance_list.append(row[‘high']/row[‘open'])
    return disftance_list

iterrows代码如下,yield语句挂起该函数并向调用者发送回一组值:

# -*- coding: utf-8 -*-
"""
Created on Sun Nov  4 15:33:07 2018

@author: wenhuatang
"""
def iterrows(self):
    columns = self.columns
    klass = self._constructor_sliced
    for k, v in zip(self.index, self.values):
        s = klass(v, index=columns, name=k)
        yield k, s

 

方法3:apply()方法循环方式

          apply()方法可将函数应用于dataframe特定行或列。函数由lambda方式在代码中内嵌实现,lambda函数的末尾包含axis参数,用来告知Pandas将函数运用于行(axis = 1)或者列(axis = 0)。

实现代码如下:

df.apply(lambda row: row[‘high']/row[‘open'], axis =1)

 

方法4:Pandas series 的矢量化方式

          Pandas的DataFrame、series基础单元数据结构基于链表,因此可将函数在整个链表上进行矢量化操作,而不用按顺序执行每个值。Pandas包括了非常丰富的矢量化函数库,我们可把整个series(列)作为参数传递,对整个链表进行计算。

实现代码如下:

dftest4['rate'] = dftest4['high']/dftest4['open']

 

方法5:Numpy arrays的矢量化方式

        由于函数的矢量化实现中只使用了series的数值,因此可使用values 方法将链表从Pandas series转换为NumPy arrays,把NumPy array作为参数传递,对整个链表进行计算。

实现代码如下:

dftest5['rate'] = dftest5['high'].values/dftest5['open'].values

 

总结

          使用timeit方法对以上几种遍历方式进行执行时间测试,测试结果如下。可以看出循环执行的速度是最慢的,iterrows()针对Pandas的dataframe进行了优化,相比直接循环有显著提升。apply()方法也是在行之间进行循环,但由于利用了类似Cython的迭代器的一系列全局优化,其效率要比iterrows高很多。NumPy arrays的矢量化运行速度最快,其次是Pandas series矢量化。由于矢量化是同时作用于整个序列的,可以节省更多的时间,相比使用标量操作更好,NumPy使用预编译的C代码在底层进行优化,同时也避免了Pandas series操作过程中的很多开销,例如索引、数据类型等等,因此,NumPy arrays的操作要比Pandas series快得多。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值