有没有办法通过 lambda 函数来引用字典理解中的数据框?
Is there a way to pass a lambda function to reference the dataframe in a dictionary comprehension?
我正在尝试用 Pandas
来模拟 R 的 mutate(across())
的行为,一种单行的方法是通过字典理解。例如,如果我有一个如下所示的 DataFrame:
df.head()
>>> jam_cpi_eop bah_cpi_eop
>>> 1980-01-01 3.038 38.714
>>> 1981-01-01 3.183 42.193
>>> 1982-01-01 3.406 44.115
>>> 1983-01-01 3.974 45.653
>>> 1984-01-01 5.212 47.748
而且我想一次性获取 DataFrame 的 jam_cpi_eop
和 bah_cpi_eop
列,我可以编写以下代码:
df1 = df.assign(
**{f'l{col.name}': np.log(col) for col in [df.jam_cpi_eop, df.bah_cpi_eop]}
)
df1.head()
>>> jam_cpi_eop bah_cpi_eop ljam_cpi_eop lbah_cpi_eop
>>> 1980-01-01 3.038 38.714 1.111199 3.656201
>>> 1981-01-01 3.183 42.193 1.157824 3.742254
>>> 1982-01-01 3.406 44.115 1.225539 3.786800
>>> 1983-01-01 3.974 45.653 1.379773 3.821069
>>> 1984-01-01 5.212 47.748 1.650964 3.865937
问题是,如果我需要对新创建的列ljam_cpi_eop
和lbah_cpi_eop
进行更多操作,我不能再使用df
作为参考。有没有办法将 lambda 函数传递给字典理解中的列表?
我希望有类似以下几行的内容,但它不起作用。
### DOESN'T WORK!
df1 = df.assign(
**{f'l{col.name}': np.log(col) for col in [lambda x: x.jam_cpi_eop, x.bah_cpi_eop]})
编辑:
我需要的是在第二步中提取日志的差异。例如,以下代码有效:
df1 = df.assign(
**{f'd{col.name}': col - col.shift(1) for col in [df.jam_cpi_eop, df.bah_cpi_eop]})
但我想获取我在第一步中创建的日志变量的差异,而不是原始列的差异。
我知道我可以通过分配一个中间数据帧来做到这一点,但我想知道是否有一种方法可以在不创建中间数据帧的情况下做到这一点。
不要使用循环,只需应用向量运算:
df1_log = np.log(df1)
输出:
jam_cpi_eop bah_cpi_eop
1980-01-01 1.111199 3.656201
1981-01-01 1.157824 3.742254
1982-01-01 1.225539 3.786800
1983-01-01 1.379773 3.821069
1984-01-01 1.650964 3.865937
合并两个数据帧:
df1_combined = df1.join(np.log(df1).add_prefix('l'))
输出:
jam_cpi_eop bah_cpi_eop ljam_cpi_eop lbah_cpi_eop
1980-01-01 3.038 38.714 1.111199 3.656201
1981-01-01 3.183 42.193 1.157824 3.742254
1982-01-01 3.406 44.115 1.225539 3.786800
1983-01-01 3.974 45.653 1.379773 3.821069
1984-01-01 5.212 47.748 1.650964 3.865937
如果您不想影响其他列:
# columns on which to apply the transform
cols = ['jam_cpi_eop', 'bah_cpi_eop']
# apply transform on subset and combine
df1_combined = df1.join(np.log(df1[cols]).add_prefix('l'))
Is there a way to pass a lambda function to the list inside the dictionary comprehension?
实现此目的的一种方法是使用 DataFrame.pipe
df = (df
.pipe(lambda x: x.assign(**{f'l{col.name}': np.log(col) for col in [x.jam_cpi_eop, x.bah_cpi_eop]}))
.pipe(lambda x: x.assign(**{f'l{col.name}': col - col.shift(1) for col in [x.ljam_cpi_eop, x.lbah_cpi_eop]}))
)
结果:
jam_cpi_eop bah_cpi_eop ljam_cpi_eop lbah_cpi_eop lljam_cpi_eop llbah_cpi_eop
1980-01-01 3.038 38.714 1.111199 3.656201 NaN NaN
1981-01-01 3.183 42.193 1.157824 3.742254 0.046625 0.086053
1982-01-01 3.406 44.115 1.225539 3.786800 0.067714 0.044546
1983-01-01 3.974 45.653 1.379773 3.821069 0.154235 0.034269
1984-01-01 5.212 47.748 1.650964 3.865937 0.271191 0.044868
把它分开让它更干净;我觉得你正在跨语法扩展 mutate(这是我个人的观点):
step1 = df.pipe(np.log).add_prefix('l')
step2 = step1.sub(step1.shift()).add_prefix('d')
df.assign(**step1, **step2)
jam_cpi_eop bah_cpi_eop ljam_cpi_eop lbah_cpi_eop dljam_cpi_eop dlbah_cpi_eop
1980-01-01 3.038 38.714 1.111199 3.656201 NaN NaN
1981-01-01 3.183 42.193 1.157824 3.742254 0.046625 0.086053
1982-01-01 3.406 44.115 1.225539 3.786800 0.067714 0.044546
1983-01-01 3.974 45.653 1.379773 3.821069 0.154235 0.034269
1984-01-01 5.212 47.748 1.650964 3.865937 0.271191 0.044868
如果您想使用链接方法来复制 mutate...across,assign 和 pipe 与解包的组合可能会有所帮助(我觉得这会降低可读性):
(df.assign(**df.pipe(np.log).add_prefix('l'))
.pipe(lambda df: df.assign(**df.filter(like='l').sub(df.filter(like='l')
.shift())
.add_prefix('d'))
)
)
jam_cpi_eop bah_cpi_eop ljam_cpi_eop lbah_cpi_eop dljam_cpi_eop dlbah_cpi_eop
1980-01-01 3.038 38.714 1.111199 3.656201 NaN NaN
1981-01-01 3.183 42.193 1.157824 3.742254 0.046625 0.086053
1982-01-01 3.406 44.115 1.225539 3.786800 0.067714 0.044546
1983-01-01 3.974 45.653 1.379773 3.821069 0.154235 0.034269
1984-01-01 5.212 47.748 1.650964 3.865937 0.271191 0.044868
我正在尝试用 Pandas
来模拟 R 的 mutate(across())
的行为,一种单行的方法是通过字典理解。例如,如果我有一个如下所示的 DataFrame:
df.head()
>>> jam_cpi_eop bah_cpi_eop
>>> 1980-01-01 3.038 38.714
>>> 1981-01-01 3.183 42.193
>>> 1982-01-01 3.406 44.115
>>> 1983-01-01 3.974 45.653
>>> 1984-01-01 5.212 47.748
而且我想一次性获取 DataFrame 的 jam_cpi_eop
和 bah_cpi_eop
列,我可以编写以下代码:
df1 = df.assign(
**{f'l{col.name}': np.log(col) for col in [df.jam_cpi_eop, df.bah_cpi_eop]}
)
df1.head()
>>> jam_cpi_eop bah_cpi_eop ljam_cpi_eop lbah_cpi_eop
>>> 1980-01-01 3.038 38.714 1.111199 3.656201
>>> 1981-01-01 3.183 42.193 1.157824 3.742254
>>> 1982-01-01 3.406 44.115 1.225539 3.786800
>>> 1983-01-01 3.974 45.653 1.379773 3.821069
>>> 1984-01-01 5.212 47.748 1.650964 3.865937
问题是,如果我需要对新创建的列ljam_cpi_eop
和lbah_cpi_eop
进行更多操作,我不能再使用df
作为参考。有没有办法将 lambda 函数传递给字典理解中的列表?
我希望有类似以下几行的内容,但它不起作用。
### DOESN'T WORK!
df1 = df.assign(
**{f'l{col.name}': np.log(col) for col in [lambda x: x.jam_cpi_eop, x.bah_cpi_eop]})
编辑:
我需要的是在第二步中提取日志的差异。例如,以下代码有效:
df1 = df.assign(
**{f'd{col.name}': col - col.shift(1) for col in [df.jam_cpi_eop, df.bah_cpi_eop]})
但我想获取我在第一步中创建的日志变量的差异,而不是原始列的差异。
我知道我可以通过分配一个中间数据帧来做到这一点,但我想知道是否有一种方法可以在不创建中间数据帧的情况下做到这一点。
不要使用循环,只需应用向量运算:
df1_log = np.log(df1)
输出:
jam_cpi_eop bah_cpi_eop
1980-01-01 1.111199 3.656201
1981-01-01 1.157824 3.742254
1982-01-01 1.225539 3.786800
1983-01-01 1.379773 3.821069
1984-01-01 1.650964 3.865937
合并两个数据帧:
df1_combined = df1.join(np.log(df1).add_prefix('l'))
输出:
jam_cpi_eop bah_cpi_eop ljam_cpi_eop lbah_cpi_eop
1980-01-01 3.038 38.714 1.111199 3.656201
1981-01-01 3.183 42.193 1.157824 3.742254
1982-01-01 3.406 44.115 1.225539 3.786800
1983-01-01 3.974 45.653 1.379773 3.821069
1984-01-01 5.212 47.748 1.650964 3.865937
如果您不想影响其他列:
# columns on which to apply the transform
cols = ['jam_cpi_eop', 'bah_cpi_eop']
# apply transform on subset and combine
df1_combined = df1.join(np.log(df1[cols]).add_prefix('l'))
Is there a way to pass a lambda function to the list inside the dictionary comprehension?
实现此目的的一种方法是使用 DataFrame.pipe
df = (df
.pipe(lambda x: x.assign(**{f'l{col.name}': np.log(col) for col in [x.jam_cpi_eop, x.bah_cpi_eop]}))
.pipe(lambda x: x.assign(**{f'l{col.name}': col - col.shift(1) for col in [x.ljam_cpi_eop, x.lbah_cpi_eop]}))
)
结果:
jam_cpi_eop bah_cpi_eop ljam_cpi_eop lbah_cpi_eop lljam_cpi_eop llbah_cpi_eop
1980-01-01 3.038 38.714 1.111199 3.656201 NaN NaN
1981-01-01 3.183 42.193 1.157824 3.742254 0.046625 0.086053
1982-01-01 3.406 44.115 1.225539 3.786800 0.067714 0.044546
1983-01-01 3.974 45.653 1.379773 3.821069 0.154235 0.034269
1984-01-01 5.212 47.748 1.650964 3.865937 0.271191 0.044868
把它分开让它更干净;我觉得你正在跨语法扩展 mutate(这是我个人的观点):
step1 = df.pipe(np.log).add_prefix('l')
step2 = step1.sub(step1.shift()).add_prefix('d')
df.assign(**step1, **step2)
jam_cpi_eop bah_cpi_eop ljam_cpi_eop lbah_cpi_eop dljam_cpi_eop dlbah_cpi_eop
1980-01-01 3.038 38.714 1.111199 3.656201 NaN NaN
1981-01-01 3.183 42.193 1.157824 3.742254 0.046625 0.086053
1982-01-01 3.406 44.115 1.225539 3.786800 0.067714 0.044546
1983-01-01 3.974 45.653 1.379773 3.821069 0.154235 0.034269
1984-01-01 5.212 47.748 1.650964 3.865937 0.271191 0.044868
如果您想使用链接方法来复制 mutate...across,assign 和 pipe 与解包的组合可能会有所帮助(我觉得这会降低可读性):
(df.assign(**df.pipe(np.log).add_prefix('l'))
.pipe(lambda df: df.assign(**df.filter(like='l').sub(df.filter(like='l')
.shift())
.add_prefix('d'))
)
)
jam_cpi_eop bah_cpi_eop ljam_cpi_eop lbah_cpi_eop dljam_cpi_eop dlbah_cpi_eop
1980-01-01 3.038 38.714 1.111199 3.656201 NaN NaN
1981-01-01 3.183 42.193 1.157824 3.742254 0.046625 0.086053
1982-01-01 3.406 44.115 1.225539 3.786800 0.067714 0.044546
1983-01-01 3.974 45.653 1.379773 3.821069 0.154235 0.034269
1984-01-01 5.212 47.748 1.650964 3.865937 0.271191 0.044868