pandas:将数据映射到新列,排除某些代码

6

我有一个键和值的字典。我想要将数据框列中的数字“映射”,其中原始列是键,新列是值。

但是,任何未包含在字典中的值都应编码为999。

原始数据框:

     Col1
0    02
1    03
2    02
3    02
4    04
5    88
6    77

字典:

codes = {'01':'05',
         '02':'06',
         '03':'07',
         '04':'08'}

期望输出:

>>> df['ColNew'] = df['Col1'].map(codes)

     ColNew
0    06
1    07
2    06
3    06
4    08
5    999
6    999

除了在字典中一开始就包含999代码,我不确定该如何做到这一点。当涉及超过100个代码且只有少数代码需要与999不同时,这是令人沮丧的。


根据您在codes中提出的映射,您新输出中索引为四的值不应该是 '08' 吗? - blacksite
我修复了,抱歉! - ale19
3个回答

6

使用mapdict.get
dict.get允许你在键不存在的情况下传递一个默认值。

df['ColNew'] = df['Col1'].map(lambda x: codes.get(x, 999))

df

  Col1 ColNew
0   02     06
1   03     07
2   02     06
3   02     06
4   04     08
5   88    999
6   77    999

这也将保留dtypes。在这种情况下,这并不重要,因为列的dtypeobject

然而,如果它是int,当NaN返回时,map会将其转换为float。通过设置默认值,我们避免了类型转换。


我原本期望在map中使用fillna来处理na_action,但是它似乎根本不起作用,即使有NaN。 - EdChum
谢谢!完美运行! - ale19

1

注意:由于类型转换,这个答案比piRSquared的答案差:

你可以简单地填充NaN值。

df['ColNew'] = df.Col1.map(codes).fillna('999')

结果:

     ColNew
0    06
1    07
2    06
3    06
4    05
5    999
6    999

有趣的一点是,Series.mapna_action 参数并不像我最初想的那样作为默认映射参数。

它的目的实际上是控制 NaN 值是否受到映射函数的影响 - 如果您没有以任何方式映射它们,则通过设置 na_action='ignore' 可能会看到潜在的性能提升。


0

另一种解决方案:

new_codes = {k: codes[k] if k in codes else '999' for k in set(df['Col1'])}
df['ColNew'] = df['Col1'].map(new_codes)

df
Out[126]: 
  Col1 ColNew
0   02     06
1   03     07
2   02     06
3   02     06
4   04     08
5   88    999
6   77    999

一些时间:

%timeit df['Col1'].map({k: codes[k] if k in codes else '999' for k in set(df['Col1'])})
1000 loops, best of 3: 373 µs per loop

%timeit df['Col1'].map(lambda x: codes.get(x, 999))
10000 loops, best of 3: 133 µs per loop

%timeit df.Col1.map(codes).fillna('999')
The slowest run took 92.77 times longer than the fastest. This could mean that an intermediate result is being cached.
1000 loops, best of 3: 575 µs per loop

看起来piRSquared的答案比我的快了约64%!


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