记录工作中使用pandas遇到的小坑------吃一堑,长一智
1,pandas中merge两个df,若有重复数据,会造成输出项多了(笛卡尔乘积式增长),话不多说,举例如下:
import pandas as pd
import numpy as np
df1 = pd.DataFrame()
df1['A'] = [1,1,1,2,2]
df1['B'] = [3,3,3,4,5]
# 输出df1:
A B
0 1 3
1 1 3
2 1 3
3 2 4
4 2 5
df2 = pd.DataFrame()
df2['A'] = [1,1,2,2]
df2['B'] = [3,3,4,5]
# 输出df2
A B
0 1 3
1 1 3
2 2 4
3 2 5
df = pd.merge(df1,df2,how = 'inner',on = ['A','B'])
# 输出df
A B
0 1 3
1 1 3
2 1 3
3 1 3
4 1 3
5 1 3
6 2 4
7 2 5
df1与df2中A,B取值为(1,3)的数据有重复,结果这个取值有个6个(2*3),另外两个取值为(2,4),(2,5)就表现正常。
pandas中merge虽有参数validate来控制KEY的类型,但是实际工程中,因为很难事前知晓相关信息,难以使用。若遇到这种情况,一个规避方法是显式的去重。
2,pandas中拼接两个df的函数concat
concat有多个参数,稍不注意容易出现意外情况。
用法:pandas.concat(objs, axis=0, join=‘outer’, join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, copy=True)
举个实例:
import pandas as pd
df1 = pd.DataFrame([['a', 1], ['b', 2]],columns=['letter', 'number'])
df1
letter number
0 a 1
1 b 2
df2 = pd.DataFrame([['c', 3], ['d', 4]],columns=['letter', 'number2'],index=[1,2])
df2
letter number2
1 c 3
2 d 4
pd.concat([df1, df2])
letter number number2
0 a 1.0 NaN
1 b 2.0 NaN
1 c NaN 3.0
2 d NaN 4.0
pd.concat([df1, df2],axis=1)
letter number letter number2
0 a 1.0 NaN NaN
1 b 2.0 c 3.0
2 NaN NaN d 4.0
参数axis指定拼接的方向,默认是沿着index方向(纵向)拼接,设定为1时,则沿着横向拼接。
pd.concat([df1, df2],axis=1,join='inner')
letter number letter number2
1 b 2 c 3
join决定拼接的列(或行)名如何组合。
3,pycharm运行程序多了(1)
pycharm里的工程代码累计太多,修改代码的时候,偶尔会出现异常情况。最近点击右键来运行程序的时候,工程代码的名字后面自动加了(1)。
当工程里有同名文件时,可能会出现附加了(1)来区分 ;
但是我的工程代码里没有同名文件,不过,文件目录曾发生过修改,猜测是pycharm缓存保留了相关信息;出现这样的情况可能导致意想不到的错误,更改此文件引用的文件,可能不生效!
例如py文件引用一个配置文件,修改配置文件,但是并未生效,程序也不会报错,但是结果不对。
可以将次工程文件复制到其他目录,重新用pycharm 打开解决此问题。(只是在pycharm关闭此工程,然后打开并不起作用)
4,pandas精度问题
编程时,遇到一个变量,其值本不应为负值,但是结果输出为负,仔细检查逻辑实现,没有发现问题,仔细思考,终于找到破绽,原来是精度问题。
由于计算机是二进制保存数据,无法精确保存浮点数;
pandas是数据计算的常用第三方库,没有找到很权威的关于pandas的默认精度,但是根据经验,一般来说保留6位小数是精确的,如果是9位小数以上,可能会有截断误差。
5,DataFrame作为参数传递
由于Python的参数传递是传递对象,或者说传对象的引用。df 作为对象传递的时候,函数对它的修改在函数外部依旧可见,举例如下:
df = pd.DataFrame({'old':[1,2,3]})
df:
old
0 1
1 2
2 3
def f(df):
df['new'] = 'a'
f(df)
df:
old new
0 1 a
1 2 a
2 3 a
6, pandas多行判断的掩码问题,逻辑判断字符问题
pandas的DataFrame经常需要做一些判断来挑选数据。举例如下:
import pandas as pd
df = pd.DataFrame([[3,6,7,1],[9,6,8,2],[4,6,84,4]],columns=["A","B","C","D"])
df
A B C D
0 3 6 7 1
1 9 6 8 2
2 4 6 84 4
# 正确使用方法
df[(df["A"]>3)&(df["D"]<3)]
A B C D
1 9 6 8 2
# 错误方法
# df[(df["A"]>3)and(df["D"]<3)]
# df[df["A"]>3&df["D"]<3]
# ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()
这里有两个关键点
第一个,关键字and / or 与使用逻辑操作符 & / |;它们的区别是 and和or判断整个对象是真是假,而&和|是指每个对象中的比特位,是元素的比特。这里我们的需求肯定是对每一行进行判断,挑选出符合要求的行,所以用逻辑操作符&。
第二个,必须在外部表达式周围放置大括号,因为python总是会尝试解析第一个按位运算符和其他比较运算符!!
7 transform函数
API:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.transform.html
先举一个实例:
df = pd.DataFrame({'A': range(5), 'B': range(1, 6),'C':['a','a','a','b','b']})
A B C
0 0 1 a
1 1 2 a
2 2 3 a
3 3 4 b
4 4 5 b
df['diff'] = df.groupby(['C'])['B'].transform(lambda x: x-x.min())
A B C diff
0 0 1 a 0
1 1 2 a 1
2 2 3 a 2
3 3 4 b 0
4 4 5 b 1
Produced DataFrame will have same axis length as self.
即transform函数会返回跟原来的DataFrame相同行数(列数)的数据;如果分组计算时,会以广播的形式填充。
在pandas版本较低时可能出现lambda函数出错。
8 DataFrame根据条件赋值
一般通过pandas的掩码特性来实现;
不太好的写法:
df['col_1'][df['col_2']>10] = 0
这样出现警告:SettingWithCopyWarning:A value is trying to be set on a copy of a slice from a DataFrame
chained indexing
这就是出现警告的原因, 我们在使用pandas中要极力避免出现chained index)
推荐写法:
df.loc[df['col_2']>10,'col_1']=0
1151

被折叠的 条评论
为什么被折叠?



