Pandas Lookup 即将被弃用 - 一种优雅高效的替代方案

8

未来版本中将弃用Pandas的lookup功能。如警告所建议的,推荐使用 .melt.loc 作为替代方案。

df = pd.DataFrame({'B': ['X', 'X' , 'Y', 'X', 'Y', 'Y', 
                         'X', 'X', 'Y', 'Y', 'X', 'Y'],
                   'group': ["IT", "IT", "IT", "MV", "MV", "MV", 
                             "IT", "MV", "MV", "IT", "IT", "MV"]})

a = (pd.concat([df, df['B'].str.get_dummies()], axis=1)
     .groupby('group').rolling(3, min_periods=1).sum()
     .sort_index(level=1).reset_index(drop=True))        

df['count'] = a.lookup(df.index, df['B'])

>  Output Warning:  <ipython-input-16-e5b517460c82>:7: FutureWarning:
> The 'lookup' method is deprecated and will be  removed in a future
> version. You can use DataFrame.melt and DataFrame.loc as a substitute.

然而,替代方案似乎不够优雅且速度较慢:

b = pd.melt(a, value_vars=a.columns, var_name='B', ignore_index=False)
b.index.name='index'
df.index.name='index'
df = df.merge(b, on=['index','B'])

有没有更优雅和更高效的方法来解决这个问题?

4个回答

3

看起来,你只需要使用索引就可以分配新值。

dfn = df.set_index('B', append=True)
dfn['count'] = a.stack()

1

您需要使用索引查找来替换已弃用的lookup

idx, cols = pd.factorize(df['B'])

df['count'] = a.reindex(cols, axis=1).to_numpy()[np.arange(len(df)), idx]

输出:

    B group  count
0   X    IT    1.0
1   X    IT    2.0
2   Y    IT    1.0
3   X    MV    1.0
4   Y    MV    1.0
5   Y    MV    2.0
6   X    IT    2.0
7   X    MV    1.0
8   Y    MV    2.0
9   Y    IT    2.0
10  X    IT    2.0
11  Y    MV    2.0

这似乎是假定我们希望所有行都包含在查找中。那么如果需要特定选择的行呢? - Danny

1

一种想法是使用DataFrame.stackDataFrame.join进行匹配,通过indexB进行匹配:

df1 = df.rename_axis('i').join(a.stack().rename('count'), on=['i','B'])
print (df1)
    B group  count
i                 
0   X    IT    1.0
1   X    IT    2.0
2   Y    IT    1.0
3   X    MV    1.0
4   Y    MV    1.0
5   Y    MV    2.0
6   X    IT    2.0
7   X    MV    1.0
8   Y    MV    2.0
9   Y    IT    2.0
10  X    IT    2.0
11  Y    MV    2.0

0

其他解决方案认为您希望在DataFrame的所有行上执行查找,而实际上您的示例确实这样做了。然而,原始函数允许提供一组坐标对,其中包括一个行索引列表和一个列名列表。

以下方法允许完整的功能,并且似乎在大约相同的时间内(稍微更快)与df.lookup一样有效:

a.to_numpy()[a.index.get_indexer(df.index), a.columns.get_indexer(df['B'])]

或者用更符合旧的 df.lookup API 的代码来表达:

df.to_numpy()[df.index.get_indexer(row_labels), df.columns.get_indexer(col_labels)]

我在一个非常小的和一个适度大(100k x 4)的数据框上测试了旧的查找函数和这个新方法各100,000次,在两种情况下,这种替代方法运行速度略快(39秒比41.5秒)


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