如何在Pandas中创建lazy_evaluated数据帧列

big*_*bug 12 python lazy-evaluation pandas

很多时候,我有一个大数据框df来保存基本数据,并且需要创建更多列来保存由基本数据列计算的衍生数据.

我可以在Pandas中这样做:

df['derivative_col1'] = df['basic_col1'] + df['basic_col2']
df['derivative_col2'] = df['basic_col1'] * df['basic_col2']
....
df['derivative_coln'] = func(list_of_basic_cols)
Run Code Online (Sandbox Code Playgroud)

Pandas将同时为所有派生列计算和分配内存.

我现在想要的是有一个懒惰的评估机制来推迟派生列的计算和内存分配到实际需要的时刻.有点将lazy_eval_columns定义为:

df['derivative_col1'] = pandas.lazy_eval(df['basic_col1'] + df['basic_col2'])
df['derivative_col2'] = pandas.lazy_eval(df['basic_col1'] * df['basic_col2'])
Run Code Online (Sandbox Code Playgroud)

这将节省像df['derivative_col2']Python'yield '生成器那样的时间/内存,因为如果我发出命令只会分解特定的计算和内存分配.

lazy_eval()熊猫怎么办?任何提示/思考/参考都是受欢迎的.

Jef*_*eff 10

从0.13(很快发布)开始,你可以做这样的事情.这是使用生成器来评估动态公式.通过eval的在线分配将是0.13中的附加功能,请参见此处

In [19]: df = DataFrame(randn(5, 2), columns=['a', 'b'])

In [20]: df
Out[20]: 
          a         b
0 -1.949107 -0.763762
1 -0.382173 -0.970349
2  0.202116  0.094344
3 -1.225579 -0.447545
4  1.739508 -0.400829

In [21]: formulas = [ ('c','a+b'), ('d', 'a*c')]
Run Code Online (Sandbox Code Playgroud)

使用创建一个评估公式的生成器eval; 分配结果,然后产生结果.

In [22]: def lazy(x, formulas):
   ....:     for col, f in formulas:
   ....:         x[col] = x.eval(f)
   ....:         yield x
   ....:         
Run Code Online (Sandbox Code Playgroud)

在行动中

In [23]: gen = lazy(df,formulas)

In [24]: gen.next()
Out[24]: 
          a         b         c
0 -1.949107 -0.763762 -2.712869
1 -0.382173 -0.970349 -1.352522
2  0.202116  0.094344  0.296459
3 -1.225579 -0.447545 -1.673123
4  1.739508 -0.400829  1.338679

In [25]: gen.next()
Out[25]: 
          a         b         c         d
0 -1.949107 -0.763762 -2.712869  5.287670
1 -0.382173 -0.970349 -1.352522  0.516897
2  0.202116  0.094344  0.296459  0.059919
3 -1.225579 -0.447545 -1.673123  2.050545
4  1.739508 -0.400829  1.338679  2.328644
Run Code Online (Sandbox Code Playgroud)

因此,其用户确定了评估的订购(而不是按需).理论上numba支持这一点,所以大熊猫可能支持这个作为后端eval(目前使用numexpr进行即时评估).

我的2c.

懒惰的评估很好,但是很容易通过使用python自己的continuation/generate特性来实现,所以尽可能将它构建成pandas是非常棘手的,并且需要一个非常好的用例通常很有用.


unu*_*tbu 6

您可以子类化DataFrame,并将列添加为属性.例如,

import pandas as pd

class LazyFrame(pd.DataFrame):
    @property
    def derivative_col1(self):
        self['derivative_col1'] = result = self['basic_col1'] + self['basic_col2']
        return result

x = LazyFrame({'basic_col1':[1,2,3],
               'basic_col2':[4,5,6]})
print(x)
#    basic_col1  basic_col2
# 0           1           4
# 1           2           5
# 2           3           6
Run Code Online (Sandbox Code Playgroud)

访问属性(通过x.derivative_col1,下面)调用derivative_col1LazyFrame中定义的函数.此函数计算结果并将派生列添加到LazyFrame实例:

print(x.derivative_col1)
# 0    5
# 1    7
# 2    9

print(x)
#    basic_col1  basic_col2  derivative_col1
# 0           1           4                5
# 1           2           5                7
# 2           3           6                9
Run Code Online (Sandbox Code Playgroud)

请注意,如果您修改基本列:

x['basic_col1'] *= 10
Run Code Online (Sandbox Code Playgroud)

派生列不会自动更新:

print(x['derivative_col1'])
# 0    5
# 1    7
# 2    9
Run Code Online (Sandbox Code Playgroud)

但是,如果您访问该属性,则重新计算值:

print(x.derivative_col1)
# 0    14
# 1    25
# 2    36

print(x)
#    basic_col1  basic_col2  derivative_col1
# 0          10           4               14
# 1          20           5               25
# 2          30           6               36
Run Code Online (Sandbox Code Playgroud)