参数化的字符串格式会产生意外结果

时间:2018-09-08 15:12:34

标签: python string pandas formatting

我有一个数据帧,其中包含一个微数据集的数据字典,包括字符串字段的字段宽度,其中这些字段填充为零。

我最终希望使用该数据帧为每个变量创建一个转换器字典,以传递给pd.read_csv调用,其中转换器函数lambda一个字符串格式化程序,其参数化宽度随每个变量而变化。

换句话说,我想生成一个函数字典,每个函数都有自己的字符串格式模板,以便可以使用适当的零填充将每个变量加载到下游。

  • 为此,我对行进行迭代,并使用表示宽度的变量创建具有可变宽度的字符串格式化程序表达式。这似乎可行。

  • 我将此格式化程序存储在字典中,每一行都有一个条目。

但是,问题是当我随后对字典进行键入并传递一个参数时,无论字符串宽度参数是什么,它的长度都是4。

示例:

# dict for storing the mapping
coll={}

# mock data (var name and associated width)
df=pd.DataFrame(data={'nme':['a','b','c','d'],'width':[2,2,3,4]})

# iterate rows
for _,dta in df.iterrows():

    # create variable width format string from width variable
    # mix of old / new string format approach

    formatstring = ('{:0>%s}'%dta.width)

    # turn string into a function, with string to be padded as argument

    formatfunc = lambda x: formatstring.format(x)
    coll[dta.nme]=formatfunc

    print 'var {}; width {}'.format(dta.nme, dta.width)
    print formatstring

运行结果如下-值得注意的是,字符串格式化程序看起来像犹太洁食,宽度可变。

var a; width 2
{:0>2}
var b; width 2
{:0>2}
var c; width 3
{:0>3}
var d; width 4
{:0>4}

但是当我在coll字典中键入一个条目时,我总是得到长度为4的填充。我错过了什么,这是一种实用的方法吗?

coll['a'](3)
'0003'

在这里,我期望键a的长度为2的填充字符串。相反,我得到的长度为4。

1 个答案:

答案 0 :(得分:1)

这是因为您的lambda在计算时使用的是全局变量formatstringformatstring等于{:0>4},即上一次迭代中为其设置的值。

另一个更简单的示例:

y = 5
f = lambda x: print(x+y)
f(2) # prints 7
y = 10
f(2) # prints 12


如何解决这个问题

解决此问题的一种方法是完全摆脱lambda。一个骇人听闻的例子:

df.set_index('nme',inplace=True)
coll = df.to_dict(orient='index')   

'0'*coll['a']['width']+str(3)  # prints '003'

如果需要,可以将最后一行转换为函数(或lambda)。