pandas——assign函数个人见解
注:本文仅代表个人见解,如有错误欢迎指正。
写在前边:最近又要捡起pandas,之前也都是处理一些简单的分类计算的操作,突然了解到assign函数,着手撸代码的时候,发现自己定义的函数在运用assign函数的时候怎么都达不到自己想要的结果,我想要每一行都能通过assign调用我的自定义函数,然后生成新的一列,但总是只能作用第一行,上网搜半天千篇一律都是照搬官方文档,所以试着一步步分析了一下源码,才发现原来是这样!
assign
assign的官方解释为“利用现有的列创建新列,并返回一个包含新列的全新dataframe,如果已存在的列则会直接覆盖”,个人理解就是通过assign函数类生成一个全新的dataframe,并且包含了你想要的计算的数据,存储在自定义的列名中。
assign需要传递的参数类型为**kwargs,其中key为新增一列的列名,value为新增一列的列值, 并且会生成一个全新的dataframe。 其中,如果value是可调用的函数,会优先调用函数后,将函数生成的值重新赋值给以key值为列名的新列,注意,这里的函数如果是自定义函数,必须返回可生成新列的数据类型。
通过分析assign的源码可知,传递的字典参数的value要么是与源数据行数相同的列表, 要么是可以生成与源数据行数相同列表的函数(这里的列表并不是单一指python中的列表类型)。 注意:当传递的参数为字典时,value只能是列表;当传递A=B的形式时,key值不能为字符串,所以只能 传递英文字母等其他符合python命名规范的参数,value则既可为列表,也可传递函数。
代码说明如下:
1 a = np.arange(1, 13).reshape(3, 4) 2 df = pd.DataFrame(a, columns=list('abcd')) 3 df = df.assign( 4 A=lambda x: x['a'] + 1 5 ) 6 print(df) 7 >>> 8 a b c d A 9 0 1 2 3 4 2 10 1 5 6 7 8 6 11 2 9 10 11 12 10
通过代码可以发现,调用assign的逻辑其实等同于:
1 df['A'] = df['a'] + 1
但assign不会污染源数据。 同样的也可传递自定义函数,但自定义函数必须返回与源数据行数相同的列表,这点其实通过上边等价关系可以看出来,因为df['a'] + 1返回的就是完美适配源数据的series类型,所以对应上文说的value不一 定是python中的列表类型,所有可用于panda生成新列的类型都可以。
代码说明如下:
1 def add_(x):
2 result = []
3 for value in x.values:
4 result.append(value + 1)
5 return result
6
7
8 a = np.arange(1, 13).reshape(3, 4)
9 df = pd.DataFrame(a, columns=list('abcd'))
10 df1 = df.assign(
11 A=lambda x: add_(x['a'])
12 )
13 print(df1)
14 >>>
15 a b c d A
16 0 1 2 3 4 2
17 1 5 6 7 8 6
18 2 9 10 11 12 10
总结:assign函数等同于df['key'] = value,但assign会生成新的dataframe,不会污染源数据,并且 assign可同时作用于多列。(遇到问题还是要多看源码,投机取巧不可取!)
本博客为记录本人遇到问题时所找到的解决方案,且均经过本人亲测可用,如有侵权请联系添加来源或删除文章,谢谢。