【问题标题】:Method to create lambda functions from list [duplicate]从列表创建 lambda 函数的方法
【发布时间】:2019-06-30 06:36:34
【问题描述】:

前言

虽然这个问题涉及pandasnumpy 包,但我相信解决方案不需要了解这些包中的任何一个。

设置

我希望创建一个 lambda 函数字典以传递给 pandas 函数 pandas.DataFrame.to_latex 的格式化程序参数。

我希望 lambda 函数字典将浮点数格式化为列表指定的数字。

示例

我想达到的效果最好通过例子来说明。让我们设置一些我们想要格式化的浮点数:

import numpy as np
import pandas as pd

y = np.array([[0.12345, 0.12345, 0.12345]])
colnames = ['col1', 'col2', 'col3']
df = pd.DataFrame(y, columns=colnames)

#print(df)
#      col1     col2     col3
#0  0.12345  0.12345  0.12345

太好了,现在我想格式化列 col1 以显示小数点后的 1 位数字。同样,我想格式化 col2 以显示小数点后的 2 位数字和 col3 以显示 3 位数字。让我们为此目的设置一个列表:

digits = [1, 2, 3]

从这个列表中,我们将创建一个 lambda 函数的字典来格式化列,并在创建后测试函数。

fun = {}

for id, col in enumerate(['col1', 'col2', 'col3']):
    fun[col] = lambda x : '{{:.{}f}}'.format(digits[id]).format(x)
    print(fun[col](0.12345))
    # Prints 0.1, 0.12, 0.123 (looks to have worked!)

在上面打印每个条目的代码中,我已经实现了我想要的。然而,再看我发现我错了

print(fun['col1'](0.12345)) # Prints 0.123
print(fun['col2'](0.12345)) # Prints 0.123
print(fun['col3'](0.12345)) # Prints 0.123

我了解这些函数在循环后都将浮点格式设置为与digits[id] = 3 相同。

我想改变我创建 lambda 函数的方式,以便我们观察:

print(fun['col1'](0.12345)) # Prints 0.1
print(fun['col2'](0.12345)) # Prints 0.12
print(fun['col3'](0.12345)) # Prints 0.123

可以这样做吗?我想一个解决方案可能涉及使用eval,但我无法弄清楚。

明显的解决方案

pd.DataFrame.to_latex 的上下文之外,我们可以创建一个 lambda 函数,它接受两个参数并根据需要格式化浮点数:

fun = lambda x, digit : '{{:.{}f}}'.format(digit).format(x)

print(fun(0.12345, digits[0])) # Prints 0.1
print(fun(0.12345, digits[1])) # Prints 0.12
print(fun(0.12345, digits[2])) # Prints 0.123

但是,据我了解,传递给 pd.DataFrame.to_latex 的格式化程序函数可能只需要一个参数,因此这样的解决方案不可行。

【问题讨论】:

  • 我猜您的问题的标题具有误导性。可能您想了解更多关于闭包的信息,因此您会找到几个问题的答案,例如 here
  • @JoergVanAken 你说得对,我不知道闭包,因此很难说清楚。您的链接帮助我理解并提供了非常丰富的信息。

标签: python python-3.x pandas dictionary lambda


【解决方案1】:

你需要在循环的时候绑定float分辨率的值,否则3个lambda闭包引用同一个id变量,都会得到最后一个赋值给id的值。

使用functools.partial的可能解决方案

def col_resolution(resolution, x):
    return '{{:.{}f}}'.format(resolution).format(x)

for id, col in enumerate(['col1', 'col2', 'col3']):
    fun[col] = partial(col_resolution, digits[id])

    # one line with lambda
    # fun[col] = partial(lambda res, x : '{{:.{}f}}'.format(res).format(x), digits[id])

【讨论】:

  • 优秀。这可以按需要工作。我还发现fun[col] = lambda x, digits=digits[id] : '{{:.{}f}}'.format(digits).format(x) 在循环期间绑定了digits[id]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-27
  • 1970-01-01
  • 1970-01-01
  • 2016-02-26
相关资源
最近更新 更多