pandas采坑记录

记录工作中使用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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值