Python 循环遍历列的有效方法

Python 循环遍历列的有效方法,python,pandas,loops,Python,Pandas,Loops,我的数据集如下所示: import pandas as pd data = {'stringID':['AB CD Efdadasfd','RFDS EDSfdsadf dsa','FDSADFDSADFFDSA']} data = pd.DataFrame(data) data['Index1'] = [[3,6],[7,9],[5,6]] data['Index2'] = [[4,8],[10,13],[8,9]] 我根据Index1和Index2中的值计算了一个volumn,这两个值都是

我的数据集如下所示:

import pandas as pd
data = {'stringID':['AB CD Efdadasfd','RFDS EDSfdsadf dsa','FDSADFDSADFFDSA']}
data = pd.DataFrame(data)
data['Index1'] = [[3,6],[7,9],[5,6]]
data['Index2'] = [[4,8],[10,13],[8,9]]
我根据Index1和Index2中的值计算了一个volumn,这两个值都是列表,我使用索引从stringID列中切片子字符串。下面是我的计算结果:

data['Value1'] = [data['stringID'][i][data['Index1'][i][0]:data['Index2'][i][0]] for i in range(0,len(data['stringID']))]
它可以工作,但是如果我在一个大数据集中循环它,速度会非常慢。有什么更好的方法?谢谢

您可以使用DataFrame.apply

您可以预处理索引以用于在另一列中进行切片

from operator import itemgetter

data['slice'] = list(zip(data['Index1'].apply(itemgetter(0)), data['Index2'].apply(itemgetter(0))))
data['Value1'] = data.apply(lambda d: d['stringID'][slice(*d['slice'])], axis=1)
data['slice'] = list(map(lambda x: slice(*x), zip(data['Index1'].apply(itemgetter(0)), 
                                                  data['Index2'].apply(itemgetter(0)))))


data['Value1'] = data.apply(lambda d: d['stringID'][d['slice']], axis=1)
或者将切片对象直接存储在另一列中

from operator import itemgetter

data['slice'] = list(zip(data['Index1'].apply(itemgetter(0)), data['Index2'].apply(itemgetter(0))))
data['Value1'] = data.apply(lambda d: d['stringID'][slice(*d['slice'])], axis=1)
data['slice'] = list(map(lambda x: slice(*x), zip(data['Index1'].apply(itemgetter(0)), 
                                                  data['Index2'].apply(itemgetter(0)))))


data['Value1'] = data.apply(lambda d: d['stringID'][d['slice']], axis=1)
您可以使用DataFrame.apply

您可以预处理索引以用于在另一列中进行切片

from operator import itemgetter

data['slice'] = list(zip(data['Index1'].apply(itemgetter(0)), data['Index2'].apply(itemgetter(0))))
data['Value1'] = data.apply(lambda d: d['stringID'][slice(*d['slice'])], axis=1)
data['slice'] = list(map(lambda x: slice(*x), zip(data['Index1'].apply(itemgetter(0)), 
                                                  data['Index2'].apply(itemgetter(0)))))


data['Value1'] = data.apply(lambda d: d['stringID'][d['slice']], axis=1)
或者将切片对象直接存储在另一列中

from operator import itemgetter

data['slice'] = list(zip(data['Index1'].apply(itemgetter(0)), data['Index2'].apply(itemgetter(0))))
data['Value1'] = data.apply(lambda d: d['stringID'][slice(*d['slice'])], axis=1)
data['slice'] = list(map(lambda x: slice(*x), zip(data['Index1'].apply(itemgetter(0)), 
                                                  data['Index2'].apply(itemgetter(0)))))


data['Value1'] = data.apply(lambda d: d['stringID'][d['slice']], axis=1)
编辑:

正如您所说,您的真实数据集有3个以上的列,您只需在获取numpy nd array之前对3个列进行切片,如下所示:

data['Value1'] = [x[y[0]:z[0]] for x, y, z 
                           in  data[['stringID','Index1','Index2']].to_numpy()]
你无法避免循环。但是,您可以使用numpy nd array作为源来简化列表理解,以加快它的速度,例如

data['Value1'] = [x[y[0]:z[0]] for x,y,z in data.to_numpy()]
300K行上的定时:

因此,它比您的解决方案快18倍左右。

编辑:

正如您所说,您的真实数据集有3个以上的列,您只需在获取numpy nd array之前对3个列进行切片,如下所示:

data['Value1'] = [x[y[0]:z[0]] for x, y, z 
                           in  data[['stringID','Index1','Index2']].to_numpy()]
你无法避免循环。但是,您可以使用numpy nd array作为源来简化列表理解,以加快它的速度,例如

data['Value1'] = [x[y[0]:z[0]] for x,y,z in data.to_numpy()]
300K行上的定时:


因此,它大约比您的解决方案快18倍。

您是否使用apply进行了联合排序?谢谢你的主意,是的,这就是你使用apply进行联合排序的方式?谢谢你的主意,是的,这是去谢谢你的方法!我喜欢你如何预处理索引列表,使计算更加清晰。谢谢非常感谢。我喜欢你如何预处理索引列表,使计算更加清晰。谢谢你能解释一下在这种情况下x是什么吗?感谢you@April:这只是我选择用来保存每行解包值的变量名。如果您希望更详细,那么应该是这样:[sID[ix_1[0]:ix_2[0]]对于sID,数据中的ix_1,ix_2.to_numpy]。所以,sID是stringID值,ix_1是Index1值,ix_2是Index2值。好的,我想我不知道你是如何打包变量的,因为我得到了太多要解包的值的错误。@April:你的真实数据集中有多少列?如果您在示例中有3列,那么应该没有错误。我的真实数据集中确实有更多的列。您能帮助解释在这种情况下x是什么吗?感谢you@April:这只是我选择用来保存每行解包值的变量名。如果您希望更详细,那么应该是这样:[sID[ix_1[0]:ix_2[0]]对于sID,数据中的ix_1,ix_2.to_numpy]。所以,sID是stringID值,ix_1是Index1值,ix_2是Index2值。好的,我想我不知道你是如何打包变量的,因为我得到了太多要解包的值的错误。@April:你的真实数据集中有多少列?如果您在示例中有3列,那么应该没有错误。我的真实数据集中确实有更多的列