Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何执行带中断的嵌套列表理解?_Python_Pandas_Dataframe_List Comprehension - Fatal编程技术网

Python 如何执行带中断的嵌套列表理解?

Python 如何执行带中断的嵌套列表理解?,python,pandas,dataframe,list-comprehension,Python,Pandas,Dataframe,List Comprehension,我有一个大的距离数据框,我想分类 df_norms = pd.DataFrame([[0, 100, 200, 4000000]], columns=['mode', 'min', 'medium', 'max']) df_afst = pd.DataFrame([[0, 50, -1], [0, 150, -1], [0, 0, -1],

我有一个大的距离数据框,我想分类

df_norms = pd.DataFrame([[0, 100, 200, 4000000]], 
                        columns=['mode', 'min', 'medium', 'max'])

df_afst = pd.DataFrame([[0, 50, -1],
                        [0, 150, -1],
                        [0, 0, -1],
                        [0, 250, -1]], 
                       columns = ['train', 'station', 'bbh'])

Normals数据框表示,对于项0,每个距离都可以使用numpy对计算进行矢量化:

[np.min(np.argwhere(np.less(td, df_norms.values.ravel()))-1) for td in df_afst.station.values]
np.less将df_afst.station中的每个距离与df_范数中的所有值进行比较,并返回一个布尔矩阵,如果
td
小于df_范数中的相应值,则返回一个真值

例如,np.less(50[01002000000])返回:array([False,True,True,True])

使用np.argwhere,我们从1开始提取输出数组中真值的索引,因此我们减去1使其从0开始。 从那里,得到数组中为真的最小索引,这是您要查找的值


您可以在列表理解中运行所有这些,结果将是:[0,1,0,2]

您可以使用numpy对计算进行矢量化:

[np.min(np.argwhere(np.less(td, df_norms.values.ravel()))-1) for td in df_afst.station.values]
np.less将df_afst.station中的每个距离与df_范数中的所有值进行比较,并返回一个布尔矩阵,如果
td
小于df_范数中的相应值,则返回一个真值

例如,np.less(50[01002000000])返回:array([False,True,True,True])

使用np.argwhere,我们从1开始提取输出数组中真值的索引,因此我们减去1使其从0开始。 从那里,得到数组中为真的最小索引,这是您要查找的值


您可以在列表理解中运行所有这些,结果将是:[0,1,0,2]

您将从使用以下各项中受益匪浅:

假设您希望将值存储在
df_afst['station']
中(这在问题中并不完全清楚,但我是根据示例猜测),您可以执行以下操作:

cuts=df_norms.iloc[0].tolist()
bbh=pd.cut(df_afst['station',cuts,labels=False,include_lowest=True)
或者更直接地说:

bbh=pd.cut(df_afst['station',[-1100,200,float('inf')],labels=False)
结果:

>>bbh
0    0
1    1
2    0
3    2
名称:站点,数据类型:int64
当然,您可以将其指定给列


这将比Python循环(显式循环或理解循环)快几个数量级。

您将从使用:

假设您希望将值存储在
df_afst['station']
中(这在问题中并不完全清楚,但我是根据示例猜测),您可以执行以下操作:

cuts=df_norms.iloc[0].tolist()
bbh=pd.cut(df_afst['station',cuts,labels=False,include_lowest=True)
或者更直接地说:

bbh=pd.cut(df_afst['station',[-1100,200,float('inf')],labels=False)
结果:

>>bbh
0    0
1    1
2    0
3    2
名称:站点,数据类型:int64
当然,您可以将其指定给列


这将比Python循环(显式或作为理解)快几个数量级。

对于初学者,列表理解创建列表,而不是数据帧。它不仅仅是
for
循环的替代语法,列表理解也不是
for
循环的更好替代。它们在某些情况下很方便,但在这些情况之外使用它们通常会适得其反。@chepner,我的错,我一开始确实分配了数据帧,但可以理解,它崩溃了。Fopr必须调整这个例子,试着看一下数字。@Thierry Lathuille,我的经验是,在速度上,它们通常(并非总是如此)比for的更好。数量级是正常的。我只是想在这个例子中尝试一下。如果你看到数量级的差异,你的
for
循环要么效率非常低,要么做的事情与列表理解实际做的不同。对于初学者来说,列表理解创建的是列表,而不是数据帧。它不仅仅是
for
循环的替代语法,列表理解也不是
for
循环的更好替代。它们在某些情况下很方便,但在这些情况之外使用它们通常会适得其反。@chepner,我的错,我一开始确实分配了数据帧,但可以理解,它崩溃了。Fopr必须调整这个例子,试着看一下数字。@Thierry Lathuille,我的经验是,在速度上,它们通常(并非总是如此)比for的更好。数量级是正常的。我只是想在这个例子中尝试一下。如果你看到了数量级的差异,你的
for
循环要么效率非常低,要么做了一些与列表理解实际不同的事情。我当然受益于这个函数。加速速度令人难以置信。谢谢你提醒我。我当然从这个功能中受益。加速速度令人难以置信。谢谢你引起我的注意。
   train  station  bbh
0      0       50    0
1      0      150    1
2      0        0    0
3      0      250    2    
for i in [0]:
    bbh_id = i + 2
    mode = df_afst.iloc[0, i]
    r = [ix - 1 for iy, y in enumerate(df_afst[df_afst.columns[i+1]].values)
                     for ix, x in enumerate(df_norms.iloc[mode])
                         if x > y]

 # results in : [0, 1, 2, 1, 2, 0, 1, 2, 2]
[0, 1, 2 | 1, 2 | 0, 1, 2 | 2]
print('\n*** pd.cut')
cpu = time.time()
cuts = df_norms.iloc[0].tolist()
bbh3 = pd.cut(df_afst['station'], cuts, labels=False, include_lowest=True)
df_afst['bbh'] = bbh3
print('CPU {:.4f} seconds'.format(time.time() - cpu))
    
print('\n*** Using numpy and its functions')
cpu = time.time()
bbh2 = [np.min(np.argwhere(np.less(td, df_norms.values.ravel()))-1) for td in df_afst.station.values]
df_afst['bbh'] = bbh2
print('CPU {:.4f} seconds'.format(time.time() - cpu))

print('\n*** Simple loop')                
cpu = time.time()
for i in [0]:
    bbh_id = i + 2
    mode = df_afst.iloc[0, i]
    for iy, y in enumerate(df_afst[df_afst.columns[i+1]].values):
        for ix, x in enumerate(df_norms.iloc[mode]):
            if x > y:
                df_afst.loc[iy, df_afst.columns[bbh_id]] = ix - 1
                break

print('CPU {:.4f} seconds'.format(time.time() - cpu))

print('\n*** Wrong approach')                
cpu = time.time()
for i in [0]:
    bbh_id = i + 2
    mode = df_afst.iloc[0, i]
    r = [ix - 1 for iy, y in enumerate(df_afst[df_afst.columns[i+1]].values)
                     for ix, x in enumerate(df_norms.iloc[mode])
                         if x > y]
print('CPU {:.4f} seconds'.format(time.time() - cpu))
*** pd.cut
CPU 0.0131 seconds

*** Using numpy and its functions
CPU 29.4257 seconds

*** Simple loop
CPU 214.5378 seconds

*** Wrong approach
CPU 103.5768 seconds
[np.min(np.argwhere(np.less(td, df_norms.values.ravel()))-1) for td in df_afst.station.values]