1. 数据导入
1.1. pd.DataFrame()
data,ndarray (structured or homogeneous), Iterable, dict, or DataFrame
输入数据源
ndarray:
np.array()
Iterable:
[[1,2,3],[4,5,6]]
dict:
{'a':[1,2,3], 'b':[4,5,6]}
->df.columns=['a','b], df.values=[[1,2,3],[4,5,6]]
DataFrame:用一个DataFrame去套另一个DataFrame,俗称套娃?
index,Index or array-like
自定义索引名
columns,Index or array-like
自定义字段名
dtype,dtype, default None
强制转换类型,例如,dtype={‘a’: int, ‘b’: str}
1.2. pd.read_csv()
filepath_or_buffer,str, path object or file-like object
输入参数
str:可以是本地地址路径,也可以是URL
path object:具有
__fspath__
属性的对象file-like object:文件流句柄,具有
read()
方法的对象,例如:open(fp, 'r')
sep,str, default ‘,’
字段分隔符,\s+
表示把连续的空白符都当成一个分隔符
header,int, list of int, default ‘infer’
字段名所在的行
int:例如
header=0
就是第1行是字段名list of int:例如
header=[0,1]
会返回一个multi-index的dfNone:不指定行作为字段名
infer:自动判断字段名所在的行,一般上是
header=0
,但如果columns
有传参,就是header=None
names,array-like, default None
重命名字段
index_col,int, str, sequence of int / str, or False, default None
索引所在的列
int:第n-1列作为索引列
str:某一字段作为索引列
sequence of int / str:会返回一个multi-index的df
False or None:不使用索引列
usecols,list-like or callable, optional
哪些字段名是需要用到的,没被列举的字段会被忽略
prefix,str, optional
当没有指定字段名,默认以顺序的数字列表作为字段,你可以为这个数字列表加个前缀,例如,prefix='x'
的字段名就是x0, x1,...
mangle_dupe_cols,bool, default True
如果有字段名重复,就会把重复的字段名重命名,例如,x, x
会变成x, x.1
dtype,Type name or dict of column -> type, optional
转化输入数据的类型
Type name:例如,
dtype=str
,把所有数据可以转化为str的值都转化了,不可以的都保留原值dict of column:指定的字段进行类型转换,例如,
dtype={‘a’: int, ‘b’: str}
true_values,list, optional
输入中符合列表内的值替换为True
false_values,list, optional
输入中符合列表内的值替换为False
skipinitialspace,bool, default False
剔除分隔符后的空格
skiprows,list-like, int or callable, optional
跳过前面的行不读
list-like, callable:跳过前面第n行不读
int:跳过前面的n行不读
skipfooter,int, default 0
跳过后面的n行不读
nrows,int, optional
只读取n行
na_values,scalar, str, list-like, or dict, optional
哪些值被替换成na值
na_filter,bool, default True
是否检测na值,值为False的话会保留数据原来的值,不会被替换为na值。
我一般都会把这个值设为False,很多时候这个自动检测na值的功能都用不上,反而会帮倒忙,例如我有一列数据是字符串,原本这一列读出来全是str类型,然后他检测完na值后,空串就变成了np.nan值,是float类型,后面批量处理的时候就会报错。
skip_blank_lines,bool, default True
是否跳过空行
iterator,bool, default False
是否返回一个迭代器对象TextFileReader
,可以使用 get_chunk()
方法取一个区间的数据。
chunksize,int, optional
每次读n条数据,返回一个迭代器对象TextFileReader
thousands,str, optional
添加千位分隔符,返回字符串格式。例如,10000 -> '10,100'
decimal,str, default ‘.’
定义小数分隔符,没啥用,主要欧洲一些地方用','作为小数分隔符,例如decimal=','
,'1,2' -> 1.2
quotechar,str (length 1), optional
例如quotechar='"'
,"1,2,3"
,引号内的分隔符会被忽略
quoting,int or csv.QUOTE_* instance, default 0
控制csv中的引号变量,可选择参数QUOTE_MINIMAL (0), QUOTE_ALL (1), QUOTE_NONNUMERIC (2) or QUOTE_NONE (3)
一般使用quoting=3
来忽略csv文件中的所有引号参数。
escapechar,str (length 1), optional
指定一个字符作为逃逸符,常用来屏蔽分隔符,例如,escapechar='/'
,/,a
中的,
就不会被当成分隔符了
comment,str, optional
指定一个字符,忽略该字符后面的内容,常用来屏蔽注释,例如,comment='#'
, #this is a comment
就会被忽略。
encoding,str, optional
指定编码格式,一般是utf-8
error_bad_lines,bool, default True
是否 不忽略报错的行
1.3. pd.read_excel()
大多数参数跟上面的pd.read_csv
是类似的,如果参数没有描述,可以向上查找对应参数。
io,str, bytes, ExcelFile, xlrd.Book, path object, or file-like object
输入参数
bytes:
open(fp, 'wr')
ExcelFile:
pd.ExcelFile(filepath)
xlrd.Book:
xlrd.open_workbook(filepath)
sheet_name,str, int, list, or None, default 0
需要导入的sheet
str:sheet的名字,例如,
Sheet1
int:第n张sheet表
list:例如,
[0, 1, "Sheet5"]
None:所有sheet表
header,int, list of int, default 0
names,array-like, default None
index_col,int, list of int, default None
usecols,int, str, list-like, or callable default None
str:例如,“A:E” or “A,C,E:F”
None:所有字段名
list-like:列表内只能是全是int或全是str,不能混用
dtype,Type name or dict of column -> type, default None
engine,str, default None
excel文本解释器,可用解释器: “xlrd”, “openpyxl” or “odf”
true_values,list, default None
false_values,list, default None
skiprows,list-like
nrows,int, default None
na_values,scalar, str, list-like, or dict, default None
na_filter,bool, default True
thousands,str, default None
comment,str, default None
skipfooter,int, default 0
convert_float,bool, default True
把浮点型的整数转化为整形,例如,1.0 –> 1
mangle_dupe_cols,bool, default True
1.4. 其他导入方法
其他的导入方法,但我用得比较少,这里就不一一记录各个参数的用法了,下面列举一些可能会用到的方法,更多的其他方法可查阅这里
pd.read_table(),等价于pd.read_csv(io, sep='\t')
pd.read_json(),这个方法挺好用,只是平常接触到的文件比较少是json格式的。
pd.read_html(),一个比较玄学的方法,至今没搞懂他会怎样解析哪些非标准化的网页,反正这个方法我很少取用,真要用到的话,我还是选择自己把网页解析好再传进Dataframe
2. 数据导出
2.1. df.to_csv()
path_or_buf,str or file handle, default None
输出文件参数
str:本地文件路径
file handle:
open(fp, 'w', encoding='utf8')
None:返回一个字符串、
sep,str, default ‘,’
字段分隔符
na_rep,str, default ‘’
用指定值代替na值输出
float_format,str, default None
浮点型输出格式,例如:float_format='%.2f'
,1.222
-> '1.22'
columns,sequence, optional
自定义输出的字段名
header,bool or list of str, default True
是否输出字段名,如果是False
或None
,则不会输出字段名
index,bool, default True
是否输出索引列
index_label,str or sequence, or False, default None
自定义索引列的字段名
mode,str, default ‘w’
写文件的模式
encoding,str, optional
写文件的编码格式,Python 2上默认为“ASCII”和Python 3上默认为“UTF-8”
compression,str or dict, default ‘infer’
输出文件为压缩格式文件,支持压缩方式:‘gzip’, ‘bz2’, ‘zip’, ‘xz’,
PS:这个参数试了一下,好像压缩后的文件打不开,不知道是不是使用方法有问题
quoting,optional constant from csv module, Defaults to csv.QUOTE_MINIMAL
CSV模块的可选常量
quoting=1
:所有的字段输出时都会被quotechar
包裹quoting=2
:除数字字段外其他的字段输出时都会被quotechar
包裹,
quotechar,str, default ‘”’
自定义引用符
line_terminator,str, optional
自定义输出的换行符
chunksize,int or None
每次写入n行
date_format,str, default None
字符串对象转为日期对象
doublequote,bool, default True
是否控制一个字段内的引用符
escapechar,str, default None
自定义又来转义sep
和quotechar
的逃逸符
decimal,str, default ‘.’
自定义小数点标志符
2.2. df.to_excel()
大多数参数跟上面的df.to_excel
是类似的,如果参数没有描述,可以向上查找对应参数。
excel_writer,str or ExcelWriter object
输出文件参数
str:本地文件路径
ExcelWriter:
pd.ExcelWriter(fp)
,如果想要把多个df保存到一张的Excel表的不同的sheet,就要使用这种方法。
sheet_name,str, default ‘Sheet1’
输出sheet表的名字
na_rep,str, default ‘’
float_format,str, optional
columns,sequence or list of str, optional
header,bool or list of str, default True
index,bool, default True
index_label,str or sequence, optional
startrow,int, default 0
从第n行开始写入
startcol,int, default 0
从第n列开始写入
engine,str, optional
写入引擎,可选引擎: openpyxl
or xlsxwriter
,或者通过自定义 io.excel.xlsx.writer
, io.excel.xls.writer
, and io.excel.xlsm.writer
来自定义一个自己的引擎。
merge_cells,bool, default True
写入 MultiIndex and Hierarchical Rows 的 df 时,会合并单元格
encoding,str, optional
inf_rep,str, default ‘inf’
输出时,把df中的inf值替换成自定义的值
freeze_panes,tuple of int (length 2), optional
固定行和列,暂时不太懂哪种情况下要用到这个参数
特别地,下面记录一些特殊的保存文本用法
# 默认只能写入65535条url,可以将url存储为字符型 with pd.ExcelWriter(save_path, engine='xlsxwriter', option={'strings_to_urls': False}) as fw: df.to_excel(fw) # 不同的df写入同一个excel表的不同sheet中 with pd.ExcelWriter(save_path, engine='xlsxwriter') as fw: df1.to_excel(fw, sheet_name=sheet_name) df2.to_excel(fw, sheet_name=sheet_name)
3. 数据查询
下列举例基于如下的dataframe
a | b | |
---|---|---|
i0 | 1 | 4 |
i1 | 2 | 5 |
i2 | 3 | 6 |
3.1. 选取列
>>> df['a']
i0 1
i1 2
i2 3
Name: a, dtype: int64
# 逐列获取
>>> for label, col in df.items(): ...
3.2. 选取行
3.2.1. 取某一行
# 取第n行
>>> df.iloc[0]
a 1
b 4
Name: i0, dtype: int64
>>> df.iloc[[0, 1]]
a b
i0 1 4
i1 2 5
# 按index名称取行,如果有重名的索引列,会返回一个df
>>> df.loc['i0']
a 1
b 4
Name: i0, dtype: int64
>>> df.loc[['i0', 'i1']]
a b
i0 1 4
i1 2 5
3.2.2. 逐行获取
>>> for idx, row in df.iterrows(): ...
>>> for row_tuple in df.itertuples(): row_tuple
Pandas(Index='i0', a=1, b=4)
Pandas(Index='i1', a=2, b=5)
Pandas(Index='i2', a=3, b=6)
但上面这种方式特别慢,所以一般会转成
np.array
后再循环取数,例如>>> arr, index = df.values(), df.index >>> for i in range(len(arr)): ... idx, row = arr[i], index[i] ... ...
3.2.3. 取前/后几行
# 取前n行
>>> df.head(1)
a b
i0 1 4
# 取后n行
>>> df.tail(1)
a b
i2 3 6
3.2.4. 按照特定条件选取行
# 选取'a'列中值大于1的行
>>> df[df['a'] > 1]
a b
i1 2 5
i2 3 6
3.3. 选取字段
3.3.1. 按位置选取
# 下面的语句的输出结果都是一样的,输出都是2
df['a']['i1']
df.at['i1', 'a']
df.iat[1, 0]
df['a'].loc['i1']
df.loc['i1']['a']
3.3.2. 按给定条件选取
# 选取'a'列中值大于1的字段
>>> df['a'][df['a'] > 1]
i1 2
i2 3
Name: a, dtype: int64
3.4. 查询表格属性
>>> df.shape
(3, 2)
>>> df.axes
[Index(['i0', 'i1', 'i2'], dtype='object'), Index(['a', 'b'], dtype='object')]
>>> df.index
Index(['i0', 'i1', 'i2'], dtype='object')
>>> df.columns
Index(['a', 'b'], dtype='object')
>>> df.dtypes
a int64
b int64
dtype: object
3.5. 数据勘探类
>>> df.head() # 数据表前10行
>>> df.descirbe() # 数据表一些基本统计量,如均值、最大最小值、中位值等
>>> df.info() # 数据表的基本信息
>>> df.column.value_counts() # 该列各元素计数
4. 数据处理
下面的方法绝大多数都不会对原df造成修改,所以一般都要重新赋值给df,例如,df = df.drop_duplicates()
。如果想直接在原df中作出更改,则需要设置方法中有inplace
参数为True,例如,df.drop_duplicates(inplace=True)
4.1. 数值替换
4.1.1. df.replace()
to_replace,str, regex, list, dict, Series, int, float, or None
哪些值需要被替换
numeric, str, list :所有等于给出的值都会被替换
regex:正则匹配,搭配
regex
参数使用dict:每一个字段都有对应替换的值,例如,
{'a': 1, 'b': 4}
;如果不设置的value参数时,这个值代表{查询值: 替换值},例如,
{1: 100, 4: 400}
;当然也可以混合使用,例如
{'a': {1: 100}, 'b': {4: 400}}
value,scalar, dict, list, str, regex, default None
需要替换的值
limit,int, default None
最多替换n次
regex,bool or same types as to_replace, default False
是否使用正则匹配
4.2. 数据删除
4.2.1. df.drop()
labels,single label or list-like
需要删除的行或列,需要配合 axis
参数使用
axis,{0 or ‘index’, 1 or ‘columns’}, default 0
配合 labels
参数使用,0为行,1为列
index,single label or list-like
删除行
columns,single label or list-like
删除列
level,int or level name, optional
多索引表时使用,表示需要删除第几个索引
删除不满足某一条件的列时,可以采用以下隐形的删除方式
>>> df = df[df[col]>values]
4.3. 数据去重
4.3.1. df.drop_duplicates()
subset,column label or sequence of labels, optional
哪些字段名需要去重
ignore_index,bool, default False
是否重新建立索引
4.4. na值处理
4.4.1. na值判断
# 批量判断
# 哪些是na值
df.isna() # 等价于pd.isna(df)
# 哪些不是na值
df.notna() # 等价于pd.notna(df)
# 单一值判断
# 该方法遇到非数值型参数会报错
np.isnan(x)
4.4.2. 删掉带有na值的行/列
4.4.2.1. df.dropna()
axis,{0 or ‘index’, 1 or ‘columns’}, default 0
axis=0
时删行,axis=1
时删列
how,{‘any’, ‘all’}, default ‘any’
how='any'
时只要出现na值就删,how='all'
时,要所有为na值才删
thresh,int, optional
至少出现n个na值时才删
subset,array-like, optional
只在给出的字段中搜索na值
4.4.3. na值替换
4.4.3.1. df.fillna()
value,scalar, dict, Series, or DataFrame
替换的值,可以输入一个dict-like,例如,{'A': 0, 'B': 1, 'C': 2, 'D': 3}
axis,{0 or ‘index’, 1 or ‘columns’}
limit,int, default None
只替换n次
4.5. 批处理
4.5.1. df.apply()
>>> df['a'].apply(lambda x: x + 1)
i0 2
i1 3
i2 4
Name: a, dtype: int64
>>> df.apply(lambda x: [x['a'], x['b']], axis=1)
i0 [1, 4]
i1 [2, 5]
i2 [3, 6]
dtype: object
>>> df.apply(lambda x: [x['a'], x['b']], axis=1, result_type='expand')
0 1
i0 1 4
i1 2 5
i2 3 6
>>> df.apply(lambda x: [x['a'], x['b']], axis=1, result_type='broadcast')
a b
i0 1 4
i1 2 5
i2 3 6
另外,还有
df.transform()
和df.agg()
,也有类似的作用,但这些函数都有一定的限制条件,用的不多。
func,function
批处理函数,如果函数式不是太长,常使用匿名函数,例如,lambda x: pass
axis,{0 or ‘index’, 1 or ‘columns’}, default 0
按列遍历还是按行遍历,一般如果我们传入一个df,都会设置axis=1
,因为一般上我们都是按行处理数据的。
raw,bool, default False
值为False时,每次传入一个Series
,值为True时,每次传入一个np.array()
result_type,{‘expand’, ‘reduce’, ‘broadcast’, None}, default None
数据输出时是否进行额外处理,只适用于axis=1
expand
: list-like结果会被展开成两列reduce
:返回一个Series
,默认值broadcast
:返回值会按照df的shape展开
4.6. 数据类型转换
# 转换为str类型
>>> df['a'].astype('str')
# 转np.array()
>>> df.values
>>> df.to_numpy()
# 转list
>>> df.values.tolist()
4.7. 修改表格属性
df.index = [...] # 修改索引
df.columns = [...] # 修改字段名
4.8. 数学运算
pd对运算符进行了重定向,下面只举例加法运算,其他运算举一反三即可
>>> df
a b
i0 1 4
i1 2 5
i2 3 6
>>> df + 1 # 等价于 df.add(1)
a b
i0 2 5
i1 3 6
i2 4 7
>>> df + [1, 2]
a b
i0 2 6
i1 3 7
i2 4 8
>>> df.add([1, 2, 3], axis=0)
a b
i0 2 5
i1 4 7
i2 6 9
4.9. 数学统计
常用的包括df.sum()
, df.mean()
, df.max()
, df.min()
, df.idxmax()
, df.idxmax()
, df.abs()
等
以上统计的时候默认会忽略na值,并且如果某一字段中如果有非数字型字段,一般会跳过这一字段。
5. 数据插入
5.1. 插入列
# 如果字段名存在就是修改;如果不存在就是增加,此时等价于df.insert(2, 'c', [7, 8, 9])
>>> df['c'] = [7, 8, 9]
>>> df
a b c
i0 1 4 7
i1 2 5 8
i2 3 6 9
5.2. 插入行
>>> df.loc['i3'] = [7, 8] # df.iloc 不允许插入行操作
>>> df
a b
i0 1 4
i1 2 5
i2 3 6
i3 7 8
插入大量行时不推荐使用上面的方法,会非常慢,推荐把数据转化为df格式,然后使用下面数据表合并的办法。
5.3. 数据表合并
下面举例基于下列两个列表
df1:
a | b | |
---|---|---|
x0 | 1 | 11 |
x1 | 2 | 22 |
y0 | 3 | 33 |
df2:
a | c | |
---|---|---|
x1 | 2 | 22 |
y0 | 3 | 33 |
y1 | 4 | 44 |
5.3.1. 横向合并
5.3.1.1. df.merge()
# 如果不加on参数,合并时会以两个表中相同的字段名为标准进行合并
# 等价于 pd.merge(df1, df2)
>>> df1.merge(df2)
a b c
0 2 22 22
1 3 33 33
# 等价于 df1.join(df2, lsuffix='_x', rsuffix='_y')
>>> df1.merge(df2, how='left', left_index=True, right_index=True)
a_x b a_y c
x0 1 11 NaN NaN
x1 2 22 2.0 22.0
y0 3 33 3.0 33.0
right,DataFrame or named Series
合并的数据表
how,{‘left’, ‘right’, ‘outer’, ‘inner’}, default ‘inner’
合并方式
on,label or list
左右表格合并的字段名
left_on,label or list, or array-like
左表格合并的字段名
right_on,label or list, or array-like
右表格合并的字段名
left_index,bool, default False
是否使用左表格字段名作为合并的字段名
right_index,bool, default False
是否使用左表格字段名作为合并的字段名
suffixes,tuple of (str, str), default (‘_x’, ‘_y’)
字段名相同时添加的后缀名
5.3.2. 纵向合并
5.3.2.1. df.append()
# 等价于 pd.concat([df1, df2])
>>> df1.append(df2)
a b c
x0 1 11.0 NaN
x1 2 22.0 NaN
y0 3 33.0 NaN
x1 2 NaN 22.0
y0 3 NaN 33.0
y1 4 NaN 44.0
other,DataFrame or Series/dict-like object, or list of these
需要附加的数据
ignore_index,bool, default Falxzse
是否忽略索引,如果值为True,就会按数字顺序从0开始重新生成索引
verify_integrity,bool, default False
是否允许附加具有重复索引的列
pd.concat([df1, df2],axis=1)
只是单纯的合并,可以存在同名,也可以指定keys进行合并,但合并逻辑和df1.merge(df2)
不一样>>> df1 = pd.DataFrame({'a':[1,2],'b':[3,4]}) >>> df2 = pd.DataFrame({'a':[2,1],'c':[3,4]}) >>> pd.concat([df1,df2],axis=1) a b a c 0 1 3 2 3 1 2 4 1 4 >>> pd.concat([df1,df2],keys='a',axis=1) a a b 0 1 3 1 2 4 >>> df1.merge(df2) a b c 0 1 3 4 1 2 4 3
6. solution
删除a列的重复,保留b列的最大值
# faster # 方法一 df.sort_values('b').drop_duplicates(subset=['a'], keep='last') # 方法二 df.groupby('a', group_keys=False).apply(lambda x: x.loc[x['b'].idxmax()])
分成等距的10个区间,并统计各个区间内的数量
df['bin'], bin = pd.cut(list(), list(range(10)), retbins=True) df = df.merge(df.groupby('bin')['a'].count().reset_index().rename(columns={'a': 'count'}))
求差集
# pandas没有内置求差集的方法 # 下面这种方法会去除df1中重复的数据 df1 = df1.append(df2) df1 = df1.append(df2) df1.drop_duplicates() # 如果join的列只有一列,那么可以直接将其转为集合的形式进行操作 a = set(df1['left_on']) b = set(df2['right_on']) pd.Dataframe(a - b, columns=['left_on']).merge(df1, 'left')
一些使用pandas提高效率的写法:python高效循环trick