Python Pandas:查找包含numpy数组的数据框列中每行的最大值

3
我得到了一个 Pandas DataFrame,看起来像下面这样:
      values                                      max_val_idx
0    np.array([-0.649626, -0.662434, -0.611351])            2
1    np.array([-0.994942, -0.990448, -1.01574])             1
2    np.array([-1.012, -1.01034, -1.02732])                 0

df['values'] 包含长度为3的numpy数组
df['max_val_idx] 包含相应数组中最大值的索引

由于每个数组的最大元素的索引已经给出,提取每个条目的最大值的最有效方法是什么?
我知道数据存储方式有点奇怪,但我不是自己创建的。由于我需要处理大量数据(约50GB,数百个以类似方式存储的拣选数据库),因此我想知道最时间有效的方法。

到目前为止,我尝试循环遍历df ['max_val_idx] 的每个元素,并将其用作在df ['values']中找到的每个数组的索引:

max_val = []         
for idx, values in enumerate(df['values']):
     max_val.append(values[int(df['max_val_idx'].iloc[idx])])

这个有没有更快的替代方案?
2个回答

4

我建议忽略'max_val_idx'列。我认为它并没有节省时间,反而会增加语法的繁琐。下面是示例数据:

df = pd.DataFrame({ 'x': range(3) }).applymap( lambda x: np.random.randn(3) )

                                                   x
0  [-1.17106202376, -1.61211460669, 0.0198122724315]
1    [0.806819945736, 1.49139051675, -0.21434675401]
2  [-0.427272615966, 0.0939459129359, 0.496474566...

你可以像这样提取最大值:
df.applymap( lambda x: x.max() )

          x  
0  0.019812
1  1.491391
2  0.496475

一般来说,如果每个单元格只有一个数字会更加方便。如果每个单元格都有长度为3的数组,可以进行如下重新排列:

for i, v in enumerate(list('abc')): df[v] = df.x.map( lambda x: x[i] )
df = df[list('abc')]

          a         b         c
0 -1.171062 -1.612115  0.019812
1  0.806820  1.491391 -0.214347
2 -0.427273  0.093946  0.496475

然后执行标准的 pandas 操作:

df.apply( max, axis=1 )

          x  
0  0.019812
1  1.491391
2  0.496475

诚然,这并不比上述方法更容易,但总的来说,以这种形式呈现的数据将更易于处理。


1
使用np.max(df, axis=1)可能比在值上应用Python内置的max更有优势,因为numpy版本可能可以更充分地利用DataFrame的底层结构。 - Scott Colby
1
这是一个好建议,尽管我刚试了一下,速度变慢了--我不确定为什么。 - JohnE
2
@JohnE:感谢您的回答。经过对两种解决方案的快速测试,似乎您的第一种方法大约快了20倍,并且在值数组变得更大时更具可扩展性。由于此时我只需要从“value”列中提取一个数字,但如果需要对数据进行更多处理或者需要选择idx列给出的值而不仅仅是选择最大值,则我会记住您的第二种方法。 - Jannick
1
哦,这对我来说也很有趣和惊讶(第一种方法更快)。无论如何,很高兴看到这个和@scott的答案有帮助。 - JohnE

2

我不知道这种方法的速度如何比较,因为我正在构建一个包含所有行的二维矩阵,但这里有一个可能的解决方案:

>>> np.choose(df['max_val_idx'], np.array(df['values'].tolist()).T)
0   -0.611351
1   -0.990448
2   -1.012000

既然我要求最大值,那么我将不得不接受@JohnE提供的答案。 但是,一般来说,我也必须根据“df['max_val_idx']”列中给定的索引选择该值。 在这种特殊情况下,您的解决方案非常方便。 不幸的是,“df ['max_val_idx']”中数字的“dtype”为“float64”,因此我必须找到解决方法来使用这些数字作为索引(据我所读,这与安全int强制转换有关)。 干杯! - Jannick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接