java 单机接口限流处理方案
317
2022-08-26
数据分析的瑞士军刀-pandas常用操作总结
目录
pandas介绍 2
pd.MultiIndex 4
pd.StringDtype|Series.str 5
数据结构Series和DataFrame 7
通用方法 7
缺失值处理df.dropna()|df.fillna() 9
统计df.describe()|离散化和分箱pd.cut()|pd.qcut() 10
提取重复df.duplicated()|删除重复df.drop_duplicates() 13
读取excel,pandas.read_excel() 14
写excel,DataFrame.to_excel()|pd.ExcelWriter 25
Excel文件的拆分与合并 27
读写csv|txt|tsv,pandas.read_csv()|DataFrame.to_csv() 28
读取mysql,pd.read_sql()|DataFrame.to_sql() 29
index 29
选取数据 33
通过dict-like选取数据 33
通过list-like选取数据 34
通过点选取数据,Series.index_name|DataFrame.column_name 35
通过loc|iloc|at|iat|df.query()|truncate()选取数据 35
操作 38
赋值操作|apply() 38
+-*/算术运算df['列'].add()|.sub()|mul()|.div()|.floordiv()|pow() 39
排序sort_values()|sort_index() 42
连接查询(数据合并与重塑) 42
分组与聚合df.groupby() 46
数据透视表pd.pivot_table()|交叉表pd.crosstab() 47
pandas中使用excel的vlookup 48
数据处理三板斧map()|apply()|applymap()|pipe() 48
数据自动填充 50
数据转置|计算的环比同比 51
pandas介绍
高性能、易于使用;
连续内存中;
pd.MultiIndex
# from_arrays()|from_product()
from_arrays() # 参数为一个二维数组,每个元素(一维数组)来分别制定每层索引的内容,mi=pd.MultiIndex.from_arrays([['a','a','b','b'],[1,2,1,2]], names=['x','y'])
from_tuples() # 参数为一个(嵌套的)可迭代对象,元素为元组类型,元组格式为(高层索引内容, 低层索引内容),mi=pd.MultiIndex.from_tuples([('a',1),('a',2),('b',1),('b',2)], names=['x','y'])
from_product() # 使用笛卡尔积的方式来创建,参数为嵌套的可迭代对象,结果为使用每个一维数组中的元素与其他一维数组中的元素来生成索引的内容,mi=pd.MultiIndex.from_product([['a','b'],[1,2]], names=['x','y'])
df.index.names=['x','y'] # 如果没在MultiIndex中设置索引名,可用此句设置
例:
df1=df['土豆'] + df['倭瓜']
df1.columns = pd.MultiIndex.from_product([['合计'], df1.columns])
res=pd.concat([df,df1], axis=1)
pd.StringDtype|Series.str
pd.StringDtype
能保存字符串的两个类型:object-dytpe|推荐用StringDtype;
例:
df = pd.DataFrame([['a','b'],['c',1]], columns=['X', 'Y'])
df.dtypes
df.select_dytpes(include='string') # 没有数据
df = df.convert_dtypes() # 尽可能转换成期望的类型
df.dtypes
df.select_dtypes(include='string')
pd.Series(['a','b']) # 默认创建出来是object类型,需显式地指定是string类型
pd.Series(['a','b'], dtype='string') # 或dtype=pd.StringDtype(),也可用pd.Series(['a','b']).astype('string')
pd.Series(['a','b',None,1]).astype('str').astype('string') # 先转为str再转为string
Series.str
可用于以字符串的形式访问Series的值,并对其应用一些方法;
.str.strip()
.str.split() # .str.rsplit(),参数n=-1,expand=True分成列展示
.str.partition() # 只按第1个出现的分隔符进行分割,返回三元组,分割前的值、分割值、分割后的值;另.str.rpartition()
.str.replace()
.str.cat()
.str.get()
.str.slice()
.str.slice_replace()
.str.join()
.str.contains() # 参数na=0
.str.startswith() # .str.endwith()
.str.repeat()
.str.pad() # 凑够指定个字符,默认在左边填充(side有left|right|both两边填充),如.str.pad(5, fillchar='&', side='right')
.str.center() # 同.str.pad(side='both')
.str.ljust() # 同.str.pad(side='right')
.str.rjust() # 同.str.rjust(side='left')
.str.zfilll() # 用0填充
.str.encode('utf-8) # .str.decode('utf-8')
.str.get_dummies()
.str.translate() # d=str.maketrans('距':'ju','离':'li'),df['km'].str.translate(d)
.str.find() # .str.rfind()|.str.index()|.str.rindex()找不到会抛错
.str.lower() # .str.upper()|.str.title()|.str.capitalize()|.str.swapcase()大小写交换
.str.isalpha() # 是否全字母
.str.isnumeric() # isnumeric用于unicode数字|罗马数字|汉字数字(但实际项目中很少会有怪异的数字出现),isdigit用于uniceode数字|罗马数字,isdecimal只能用于unicode数字,如果只是普通阿拉伯数字这3个方法可互用
.str.isalnum()
.str.isspace()
.str.islower()
.str.istitle()
.str.match(RE, na=False) # na=False
.str.extract(RE) # 分组捕获,df['dt'].astype('str').str.extract('(\d{4})-(\d{2})-(\d{2})')
例:
df = pd.DataFrame([['\na\n', '\nd\n', datetime(2020,1,1)],['\nb\n', 1, datetime(2020,1,2)]], columns=list('ABC'))
df
df.dtypes
df['A'].str.strip()
df['B'].str.strip() # 使用.str必须保证是string类型,1和datetime不能用.str.strip()
df['B'].astype('str').str.strip()
df['C'].astype('str').str.split('-')
df['temperature'].str.replace('C', '').astype('int64')
df['name'].str.cat(['变身']*len(df), sep='^', na_rep='没有')
例,工作中处理数据:
df = pd.read_excel('Series_str.xlsx')
df.dtypes # 都为object
df = pd.read_excel('Series_str.xlsx').convert_dtypes() # 常用,读表格时直接显式转换为期望的类型,如果为object类型则说明原始数据有问题(如日期列为object而不是datetime64[ns],销量列为object而不是int64),需改原始数据
df.iloc[2,0]
df['货号'] = df['货号'].str.strip()
举例,商品处理专员;
数据结构Series和DataFrame
以excel中的数据为例:
DataFrame是2维数据;
Series是1维数据,即表格中的每一列是Series;
注:pandas没有3维以上的数据结构,而numpy中可表示任意多维;
通用方法
values # df.values,enumerate(df.values)返回行号和行内容
dtypes
astype() # 将某列转为指定类型
copy()
infer_objects() # Attempt to infer better dtypes for object columns.
convert_dtypes()
fillna()
ffill() # Synonym for :meth:`DataFrame.fillna` with ``method='ffill'``.
bfill() # Synonym for :meth:`DataFrame.fillna` with ``method='bfill'``.
replace() # df.replace('qp', 'hp', inplace=True),df.replace({'qp':'hp'}, inplace=True)字典key是原值value是要替换后的值,df.replace(['qp',], 'hp', inplace=True)列表里的多个值替换为1个值;另regex=True;df['temperature'].str.replace('C', '').astype('int64')
interpolate() # Please note that only ``method='linear'`` is supported for DataFrame/Series with a MultiIndex.
asof() # Return the last row(s) without any NaNs before `where`.
isna() # Detect missing values.
isnull()
notna()
notnull()
clip() # Trim values at input threshold(s).
asfreq() # Convert TimeSeries to specified frequency.
at_time() # Select values at particular time of day (e.g., 9:30AM).
between_time() # Select values between particular times of the day (e.g., 9:00-9:30 AM).
resample() # Resample time-series data.
first()
last()
rank()
compare() #
align() # Align two objects on their axes with the specified join method.
where() # Replace values where the condition is {cond_rev}.
mask() #
shift() # Shift index by desired number of periods with an optional time `freq`.
slice_shift() #
tshift() #
truncate() # Truncate a Series or DataFrame before and after some index value.
tz_convert() # Convert tz-aware axis to target time zone.
tz_localize() # Localize tz-naive index of a Series or DataFrame to target time zone.
abs() # Return a Series/DataFrame with absolute numeric value of each element.
describe() # Generate descriptive statistics.
pct_change() # Percentage change between the current and a prior element.
transform() # Call ``func`` on self producing a {klass} with transformed values. Produced {klass} will have same axis length as self.
first_valid_index() # Return index for {position} non-NA/null value.
last_valid_index()
import pandas as pd
# 创建Series,工作中很少用这种方式创建Series,用的多的是直接将excel表格读取为DataFrame再读取其一列作为Series
s = pd.Series([1,2,3], index=list('abc'), dtype='int64', name='num')
s1 = pd.Series({'a':1, 'b':2, 'c':3})
s2 = pd.Series(3.0, index=['a', 'b', 'c'])
s.index
s.values
s[['a','b']]
s.sort_index()
s.sort_values('b')
s.isnull()
s.notnull()
# 创建DataFrame
通过2维的list-like创建;
通过字典创建;
通过读取excel表,常用;
df = pd.DataFrame([[1,2],[3,4]], columns=['A','B'], index=['x','y']) # columns列索引index行索引
df1 = pd.DataFrame({'A':[1,3], 'B': [2,4]}, index=['x','y']) # dict的key是列索引
df1.set_index('A') # inplace=True只在index上改不要生成新的
df1.to_excel('test.xlsx', index=False) # 常用,不要行索引那列
df2 = pd.read_excel(r'c:\test.xlsx')
df.sort_index() # 按行索引排序
df.sort_values('入职日期') # 按某列排序
df.dtypes
df.columns # 查看列名,df.keys(),df.columns.values.tolist()
df.index # 返回行索引的迭代器
df['姓名']
df.loc[1] # 查第1行数据
df.loc[1]['姓名'] # 查第1行姓名列数据
df[['姓名','年龄']] # 查姓名和年龄字段数据
df.loc[0:3] # 查第0行到第2行数据
df.head() # 查前5行
df.tail() # 查后5行,df.tail(3)
df.shape # 查看数据的开头,得到tuple,几行几列
df.fillna(1) # 将空值填充为1
df.replace('test','prod') # 所有单元格替换
df.isnull() # 查看单元格数据是否为空,为空True
df.notnull() # 查看数据不为空,不为空True
df.values
df.unique() # 查看唯一值
df.reset_index(drop=True) # drop=True删除原来行索引(变为默认索引),drop=False,行索引修改为默认索引(原来行索引的那列改为普通列数据)
df.columns
df.index
df.drop(labels=[1,3], inplace=True) # 数据删除,默认inplace=False返回新对象,inplace=True在原对象上修改(常用),df.drop(0)删第0行,df.drop(labels=[1,3])删多行;df.drop('语文', axis=1)删语文列,df.drop(labels=['语文', '数学'], axis=1)删多列
df.columns = ['A','B','C'] # 改列名,必须指明每一列否则抛错
df.rename(columns={'a':'A', 'b':'B', 'c':'C'}, inplace=True) # 改列名,指定改某列,推荐
pd.merge(数据1,数据2) # 合并
pd.concat(数据1,数据2) # 合并
pd.pivot_table(数据) # 用df作数据透视表,类似excel的数透
缺失值处理df.dropna()|df.fillna()
df.dropna() # 删除空值,牵涉到对原数据修改的,如果要在原对象上改inplace=True
def dropna(self, axis=0, how="any", thresh=None, subset=None, inplace=False):
参数:
axis=0 # 0删除包含缺失值的行,1删除包含缺失值的列
how='any' # 与axis配合使用,any只要缺失值出现就删除该行或列,all所有的值都缺失才删除行和列
thresh=None # axis中至少有thresh个非缺失值,否则删除,如axis=0,thresh=10如果该行中非缺失值的数量小于10将删除这一行,用的少
subset=None # list,指定在哪些列中删空值,df.dropna(subset=['语文','数学'])
df.fillna(0)
def fillna(self, value=None, method=None, axis=None, inplace=False, limit=None, downcast=None) -> Optional["DataFrame"]:
例:
df.fillna(0)
df.fillna({'语文': 0, '数学': 555}) # 将语文列空值填充为0,将数学列空值填充为555
df.fillna(method='ffill') # method填充方式,有ffill用前面的值填充|bfill用后面的值填充|pad向后填充|backfill向前填充,如果轴变了那么左和右对应前和后
df.fillna(method='ffill', limit=2) # 仅填充2个
统计df.describe()|离散化和分箱pd.cut()|pd.qcut()
df.describe() # 会自动将数值列统计,有count|mean|std|min|25%|50%|75%|max信息
df['语文'].describe() # 指定列的统计
df.mean() # 所有列的mean
df.corr() # 返回列与列之间的相关系数
df.count() # 返回每一列中的非空值的个数
df.max() # 返回每一列的最大值
df.min() #
df.median() # 返回每一列的中位数
df.std() # 返回每一列的标准差
df['数学'].mean() # 仅数学列的mean平均值
数学统计函数:
count # 观测值的个数
sum
mean
mad # 平均绝对方差
median # 中位数
min
max
argmin # 计算能够获取到最小值的索引位置(整数)
argmax # 计算能够获取到最大值的索引位置
idxmin # 每列最小值的行索引
idxmax # 每列最大值的行索引
mode # 众数
abs # 绝对值
prod # 乘积
std # 标准差
var # 方差
sem # 标准误
skew # 偏度系数
kurt # 峰度
quantile # 分位数
cumsum # 累加
cumprod # 累乘
cummax # 累最大值
cummin # 累最小值
cov() # 协方差
corr() # 相关系数
rank() # 排名
pct_change() # 时序序列变化
def cut(
x,
bins,
right: bool = True,
labels=None,
retbins: bool = False,
precision: int = 3,
include_lowest: bool = False,
duplicates: str = "raise",
ordered: bool = True,
):
参数:
x # list,待切割的原形式,且必须为一维
bins # int,序列尺度或间隔索引,如果bins是整数(定义了x宽度范围内的等宽面数量,这种情况下x的范围在每个边上被延长1%以保证包括x的最小值或最大值),如果bins是序列(定义了允许非均匀bin宽度的bin边缘,这种情况下没有x的范围的扩展)
right # bool,是否是左开右闭区间
labels=None # 用作结果箱的标签,必须与结果箱相同长度,如果False只返回整数指标面元
retbins=False # 是否返回面元
precision=3 # int,返回面元的小数点几位
include_lowest=False # 第一个区间的左端点是否包含,返回值(若labels=False则返回整数填充的Categorical或数组或Series;若retbins=True还返回用浮点数填充的N维数组)
例:
y = [1992,1983,1922,1932,1973] # 待分箱数据
boxes = [1900, 1950, 2000] # 有2个箱子,下标分别0、1
res = pd.cut(y, boxes) # 1992在1950-2000之间,依此类推
pd.value_counts(res) # 1900-1950有几个值,1950-2000有几个值
res = pd.cut(y, boxes, labels=False) # 返回y中的值在哪个箱子里
pd.value_counts(res) # 2个箱子里的值的数量
boxes_name = ['50年代前', '50年代后']
res = pd.cut(y, boxes, labels=boxes_name)
pd.value_counts(res)
y = [1992,1983,1922,1932,1973,1990,1993,1995] # 待分箱数据
res=pd.qcut(y, q=4)
pd.value_counts(res)
def qcut(
x,
q,
labels=None,
retbins: bool = False,
precision: int = 3,
duplicates: str = "raise",
):
参数:
q # int,等频分箱,整数或分位数组成的数组,结果中超过边界的值将会变成NA
提取重复df.duplicated()|删除重复df.drop_duplicates()
df['姓名'].unique() # 返回list
df['姓名'].value_counts() # 值出现过几次
def drop_duplicates(
self,
subset: Optional[Union[Hashable, Sequence[Hashable]]] = None,
keep: Union[str, bool] = "first",
inplace: bool = False,
ignore_index: bool = False,
) -> Optional["DataFrame"]:
参数:
subset=None # 用来指定特定的列,默认是所有列
keep='first' # first|last|False,指定处理重复值的方法,frist保留第一次出现的值,last保留最后一次出现的值,False删除所有重复值留下没有出现过重复的
inplace=False # 是直接在原来数据上修改还是保留一个副本
例:
df.drop_duplicates(subset=['姓名'], keep='first') # keep='last'或keep=False
def duplicated(
self,
subset: Optional[Union[Hashable, Sequence[Hashable]]] = None,
keep: Union[str, bool] = "first",
) -> "Series":
例:
df.duplicated() # 所有行有无重复,返回True
mask=df.duplicated(subset=['姓名']) # 同df['姓名'].duplicated(),指定列有无重复
df[mask] # 列出重复的数据
读取excel,pandas.read_excel()
io # 路径|StringIO|URL
sheet_name # 选择子表,默认0选第0个,sheet_name可以是int|str|list|None,int选第几个sheet(从0开始),str传sheet名字,list中元素可以是sheet名或int类型(返回字典,key为int或sheet名,value为DataFrame对象),None全部sheet(返回字典,key为sheet名,value为DataFrame对象)
header=0 # 指定作为列索引的行(即表头),默认将第0行作为表头)
index_col=None # 指定作为行索引的列(一条记录中哪个字段为pk,将哪几列设为索引)
例:
pd.read_excel('test.xlsx', header=None)
pd.read_excel('test.xlsx', sheet_name=1) # header默认0
pd.read_excel('test.xlsx', sheet_name=2, header=1)
pd.read_excel('test.xlsx', sheet_name=3, header=[0, 1], index_col=0) # MultiIndex情况,2行共同作为表头
例:
注:index_col=[0,1] # index_col仅能传索引号,传列名会抛错;如果要传列列名用df.set_index(['年份','月份'])
例:
df = pd.read_excel('test.xlsx', header=None, names=['序号', '姓名', '年龄'], index_col='序号') # header=None告知没表头,names=[...]使用设置的自定义表头
usecols # 指定只使用哪些列,默认None,可以是None|str|int-list|str-list|函数,None全部,str即excel中标识的列ABCDE,int索引默认从0开始,str-list数据中的列
例:
pd.read_excel('test.xlsx')
pd.read_excel('test.xlsx', usecols='A,C:E')
pd.read_excel('test.xlsx', usecols=[0, 2])
pd.read_excel('test.xlsx', usecols=['AAA', 'CCC']) # 建议用此种,代码可读性好|表格中间处理时增字段时不易出错
pd.read_excel('test.xlsx', usecols=lambda x: x=='CCC')
skiprows=None # int,跳过行,如果表格中开始处有多个空行,需要把有数据的表头那行也跳过
例:
pd.read_excel('test.xlsx', skiprows=1) # excel中标记行的数字,从1开始
pd.read_excel('test.xlsx', sheet_name=1, skiprows=[0, 2]) # 第0行和第2行
pd.read_excel('test.xlsx', skiprows=8, usecols='F:I')
names # 要使用的列名列表,如果文件不包含标题行,则应显式传递header=None
例:
df = pd.read_excel('test.xlsx', header=None, names=['月份', '销量', '销售额']) # test.xlsx没有表头
dtype # 设置列的类型,字典,{'列名': '类型'},尽量明确指定列的类型,这样易操作,int64|float64|bool|datetime64|object这些类型pandas能根据excel默认识别,其它的需单独指定
int8|int16|int32|默认int64 # 整型
float16|float32|默认float64 # 浮点型
str|string # 字符串,str会识别为object类型,string会识别为string
bool # 布尔
category # 分类
datetime64[ns] # 时间戳(纳秒)
period[Y/M/D] # 时间周期
object # py对象混合类型,如Series中有多个数据类型
例:
df = pd.read_excel('test.xlsx')
df.dtypes # 如下图
df = pd.read_excel('test.xlsx', dtype={'货号': 'str', '商品代码': 'string', '颜色代码': 'str', '季节': 'category', '品牌': 'category','商品年份': 'period[Y]'}) # 商品代码int64不能直接转为string,
df['颜色代码'] = df['颜色代码'].astype('string')
df.dtypes
parse_dates=False # 指定解析成日期格式的列,通常传list类型([0,1]或['a','b'])
date_parser=None # function,解析日期格式的函数,若excel中的列是日期类型pandas默认会识别不需要传date_parser
例:
df = pd.read_excel('test.xlsx', index_col=2, parse_dates=True) # 尝试将行索引转为日期格类型
df = pd.read_excel('test.xlsx', parse_dates=[0,1,2,3,4,5,6]) # 将指定的列都转为日期类型
df.dtypes
df = pd.read_excel('test.xlsx', sheet_name=1, parse_dates=[[0,1,2]]) # 将多列合并为1列,合成的这列列名是年_月_日
df = pd.read_excel('test.xlsx', sheet_name=1, parse_dates={'日期': ['年','月','日']}) # 指定新生成的列的列名,默认的"年_月_日"改为"日期"
df = pd.read_excel('test.xlsx', parse_dates=[0], date_parser=lambda x: pd.to_datetime(x, format='%Y年%m月%d日')) # 将excel中不是日期类型的列转为日期类型x为Series对象
df.dtypes
df=pd.read_excel('test.xlsx', index_col='出生日期', parse_dates=['出生日期']) # 三步曲,1行索引为日期型,2将日期列转为日期型,3对日期列进行排序
df['1989'].head() # df['1989-10']或df['1983':'1990']这样查,行索引必须为出生日期
df.sort_values('出生日期')
df.truncate(after='1990-12') # 查此日期之后出生的人
na_values=None # missing data缺失值,默认是NaN, not a number, 是float类型
scalar标量;
常见用法:
na_values=0 # 将0替换为NaN
na_values='空值'
na_values=['空值', 0]
na_values={'列名': ['空值', 0]}
例:
df = pd.read_excel('test.xlsx', na_values=0) # excel中的单元枨若是空格或空白字符,不会解析为NaN
df = pd.read_excel('test.xlsx', na_values=['a', ' ', 0]) # 将'a',空格,0替换为NaN
df = pd.read_excel('test.xlsx', na_values={'列1': ['a',' ', 0]}) # 仅将列1中的数据替换为NaN
converters=None # 转换器,传dict,key为列名,value为函数
例:
df = pd.read_excel('test.xlsx', converters={'货号': lambda x: x.strip()}) # 同converters={'货号': lambda: str.strip}
true_values=None # 将指定的值转为bool的True,传list,只对字符串生效,仅当该列所有数据都能转才转(要么都转,要么都不转)
false_values=None # 将指定的值转为bool的False, 传list
例:
df = pd.read_excel('test.xlsx', true_values=['a','b'], false_values=['c','d'])
df = pd.read_excel('test.xlsx', true_value=['a','b'],false_value=['c','d'], dtype={'列3': bool}) # 0为False非0为True
squeeze=False # 默认False返回DataFrame,True返回Series
mangle_dupe_cols=False # 是否重命名重复列名
nrows=None # 要解析的行数,int,不包括表头
thousands=None # 千位分隔符,用于将字符串列解析为数字
convert_float=True # 在可能的情况下,是否将float转换为int
写excel,DataFrame.to_excel()|pd.ExcelWriter
excel_writer # 文件路径|ExcelWriter类
index=True # 是否输出index
例:
df = pd.DataFrame({'销量': [10, 20], '售价': [100,200]})
df.to_excel('tb.xlsx', index=False)
df = pd.DataFrame({'销量': [10,20], '售价': [100.01,None]}, index=['aa','bb'])
df.index.name = '货号'
df.to_excel('tb.xlsx', sheet_name='tb1', float_format='%.2f',na_rep='我是空值') # 是索引的字段,其数据字体会加粗
pandas.ExcelWriter类,2个作用:设置datetime输出格式(默认会输出年月日时分秒)|输出多个sheet
with pd.ExcelWriter('tb.xlsx', datetime_format='YYYY-MM-DD') as writer:
df1.to_excel(writer, sheet_name='AAA')
df2.to_excel(writer, sheet_name='BBB')
例:
df1 = pd.DataFrame({'日期': [datetime(2020,1,1), datetime(2020,1,2)], '销量': [10, 20]})
df2 = pd.DataFrame({'日期': [datetime(2020,2,1), datetime(2020,2,2)], '销量': [30, 40]})
print(df1)
print(df2)
with pd.ExcelWriter('tb.xlsx', datetime_format='YYYY-MM-DD') as writer:
df1.to_excel(wirter, sheet_name='1月')
df2.to_excel(writer, sheet_name='2月')
Excel文件的拆分与合并
一个文件夹下多个工作簿的合并(单独Sheet)
例:
p = 'c:/dir/'
result = pd.DataFrame()
for fn in os.listdir(p):
df = pd.read_excel(p+fn)
result = pd.concat([result, df])
result.to_excel('c:/dir/result.xlsx')
同一工作簿中多个Sheet合并
例:
p = 'c:/dir/'
df = pd.read_excel(p+fn, sheet_name=None)
result = pd.DataFrame()
for f in list(df.keys()):
new_field_df = df[f]
result = pd.concat([result, new_field_df])
result.to_excel('c:/dir/result.xlsx')
将一个工作表拆分成多个工作表
例,按部门名称拆:
df = pd.read_excel('test.xlsx')
departments = list(df['部门'].drop_duplicates()) # 所有部门名称
result = pd.ExcelWriter('c:/dir/result.xlsx')
for f in departments:
df1 = df[df['部门'] == f]
df1.to_excel(df1, sheet_name=f)
result.save()
result.close()
将一个工作表拆分成多个工作簿
例,按部门名称拆:
df = pd.read_excel('test.xlsx')
departments = list(df['部门'].drop_duplicates()) # 所有部门名称
for f in departments:
df1 = df[df['部门'] == f]
df1.to_excel('c:/{}.xlsx'.format(f))
读写csv|txt|tsv,pandas.read_csv()|DataFrame.to_csv()
pandas.read_csv()参数:
filepath # 路径
sep=',' # 分隔符默认逗号
encoding=None # utf8|utf-8|gbk|gb2312|gb18030
header='infer' # header=None告知没表头,如果有int类型header=0
names=['姓名', '性别', '年龄', '手机', '地址', '入职日期'] # 自定义表头,要和header=None连用
index_col=None # 一条记录的主键,index_col='姓名'
skiprows=None # 跳过指定行,skiprows=[2,3]
nrows=None # 仅显示几行,nrows=3
另pandas.read_table(),sep='\t'分隔符默认制表符;
df.to_csv()参数:
path_or_buf # 路径
sep=',' #
encoding='utf8'
例:
df = pd.DataFrame({'一': [1,2],'二': [3,4]})
df.to_csv('tb1.csv', index=False)
df = pd.read_csv('tb1.csv') # 注意编码,写和读要一致
df.shape # 几行几列
df.head() # 默认前5行,没有表头会把第一行数据作为表头
df.columns # 显示表头
df.index # 行索引号
df.dtypes
读取mysql,pd.read_sql()|DataFrame.to_sql()
con = pymysql.connect(host='localhost',user='root',password='1234',database='test',charset='utf8')
df = pd.read_sql('select * from test', con=con)
df
index
pandas官方给自定义的字符串索引为label(标签索引),内置的数字为integer position(位置索引)是默认0开始自动生成的;
使用索引应避免2种情况:索引有重复;用非默认的整数(即自定义的索引都用字符串,不用整数,避免与默认的位置索引歧义);
3个作用:识别;对齐;获取和设置;
识别:
对于Series一维数据,3月为索引就识别出3所代表的意义;
对于DataFrame二维数据,行索引(3月)和列索引(销量|收入)用于识别30所代表的意义;
对齐:
在对Series和DataFrame作运算时,一般不需要我们显式地指定;
对于2个Series相加,先通过将索引对齐,再操作;
再对DataFrame操作:
若追加或拼接,会先将列索引对齐,再拼接操作;
若左右拼接,会先将行索引对齐,再拼接操作;
获取和设置:
选取数据
通过dict-like选取数据
例:
s = pd.Series({'A': 1, 'B': 2, 'C': 3})
df = pd.DataFrame({'A':[1,4,7],'B':[2,5,8],'C':[3,6,9]}, index=['X','Y','Z'])
s['C'] # s.get('C')
df['B'] #
s[1] # 是通过list-like选取数据
df[2] # 抛错
s[['B','C']]
df[['B']]
s[[True,False,True]]
df[[True,False,True]]
mask = s>1
s[mask] # 将>1的数据筛选出来,同s[s>1]
mask = df['B']>2 # 返回False True True
df[mask] # 工作中用的最多
df[(df['B']>2) & (df['B']<6)] # &|~
df[(df['B']==2) | (df['B']==8)]
df[~(df['B']==2)]
通过list-like选取数据
通过位置索引切片,包括头不包括尾;
通过标签索引切片,包括头和尾;
例:
s = pd.Series({'A': 1, 'B': 2, 'C': 3})
df = pd.DataFrame({'A':[1,4,7],'B':[2,5,8],'C':[3,6,9]}, index=['X','Y','Z'])
s[0:2]
s[0:-1]
s[::-1] # 反过来
s[::2] # 步长为2
df[0:2] # 结果为前2行
s['A':'B']
df['X':'Y']
通过点选取数据,Series.index_name|DataFrame.column_name
只了解不推荐使用,代码可读性不好|有可能与方法或属性冲突;
例:
s = pd.Series([1,2,3,4], index=['total','列','sum','dtype'])
s.total # 用s['total']
s.列
s.sum() # 与Series.sum()冲突,不能用点选,只能用s['sum']
s.dtype # 与Series.dtype冲突,只能用s['dtype']
df = pd.DataFrame([[1,2,3,4],[5,6,7,8]], columns=['total','列', 'sum', 'dtypes'])
df.total
df.列
df.sum()
df.dtypes # df['dtypes']
通过loc|iloc|at|iat|df.query()|truncate()选取数据
df.loc[row_indexer, column_indexer] # 使用标签索引,使用切片时前后都包
例:
df = pd.DataFrame([[1,2,3,4],[5,6,7,8],[9,10,11,12]], columns=list('ABCD'), index=list('XYZ'))
df.loc['Y'] # 行索引,若读进来的数据中设置了行索引为id则此处可用id作为行索引,如pd.read_excel('test.xlsx', index_col='id')
df.loc['Y', 'C'] # 行索引+列索引,定位至一单元格
df.loc[['X','Y'],['B','D']] # 多行索引+多列索引
df.loc['Y':'Z', 'B':'D'] # 切片
df.loc['Y':'Z', ['B', 'D']] # 混合使用
df.loc[:, ['B','D']] # 全部行+多列索引
df.loc[:, ::-1] # 全部行+反向全部列
df.loc[[True, False, True], [True, False, True, False]]
df.loc[lambda df: [True, False, True], lambda df: [True, False, True, False]]
df = pd.read_csv('tips.csv', usecols=['total_bill', 'day', 'time'])
df = df.groupby(['day', 'time']).sum() # 方1
df = df[df['total_bill']>100]
df.groupby(['day', 'time']).sum().loc[lambda df: df['total_bill']>100] # 方2,链式调用
df.loc[(df['语文']>=60) & (df['英语']<=60)]
df.loc[df['性别']=='男', '称呼'] = '先生' # 如果性别为男,则新增称呼列为先生
df.loc[df['性别']=='女', '称呼'] = '女士'
cond1=df['性别']=='男' # 当有多个条件时条件之间一直要&,这样麻烦,用df.query()
df[cond1]
cond1="性别=='男' and 总分>=150" # cond1="姓名 in ['李平','王刚']",cond1="60<=语文<=100 and 性别=='女'"
df.query(cond1)
cond2=df['姓名'].str.startswith('王') # .str.endwith('平')|.str.contains('[a-cA-C]座'),可以是字符串或正则,case=False忽略大小写
cond3=(
'@df.出生日期.dt.year > 1980 and' # "出生日期"不能为行索引
'@df.出生日期.dt.year < 1990'
'and 性别 == "男"' # 此行and不能续在上一行后面,因为类型不一样,此行是字符串上一行日期型
)
df.query(cond3)
truncate()
截取时间区间的数据;
使用前先3步曲(如果截取数据不符合预期抛异常),1将日期字段先解析为日期类型,2再设为行索引,3并按时间先后排序;
def truncate(
self: FrameOrSeries, before=None, after=None, axis=None, copy: bool_t = True
) -> FrameOrSeries:
before : date, str, int
Truncate all rows before this index value.
after : date, str, int
Truncate all rows after this index value.
df=pd.read_excel('test.xlsx', index_col='出生日期', parse_dates=['出生日期']) # 三步曲,1行索引为日期型,2将日期列转为日期型,3对日期列进行排序
df['1989'].head() # df['1989-10']或df['1983':'1990']这样查,行索引必须为出生日期
df.sort_values('出生日期')
df.truncate(after='1990-12') # 查此日期之后出生的人
例,MultiIndex情况,多索引列的数据是有序的:
df2=df.loc[(('1班', 'a'), slice(None)),:] # slice(None)等价于:,对于多索引不能用冒号而用slice(None)
例,MultiIndex情况,且多索引的列数据是中文(无序的),先排序再筛选:
df=df.sort_index(level='科目')
df2=df.loc[('语文', slice(None)),:]
df.iloc[row_indexer, column_indexer] # i为integer,使用位置索引,注意使用切片时前包后不包
选取单个值时:
df.loc['X', 'B'] # 同df.at['X', 'B'],at和iat不能切片,同df['B'].at['X']
df.iloc[1, 2] # 同df.iat[1, 2]
例:
df = pd.DataFrame([[1,2,3,4],[5,6,7,8],[9,10,11,12]], columns=list('ABCD'), index=list('XYZ'))
df.iloc[0]
df.iloc[0, 1]
df.iloc[[0, 1], [1, 3]] # 2行2列
df.iloc[[True, False, True], [True, True, False, False]]
df.iloc[0:2, 1:3] # 前包后不包
df.iloc[lambda df: [0, 1], lambda df: [1, 3]]
操作
赋值操作|apply()
s = pd.Series([1,2,3], index=list('ABC'))
s[0] = 10
s.iloc[1] = 11
s.loc['C'] = 12
s.loc['D'] = 13 # 只能用loc追加
s.iloc[1:3] = 20
s.loc['C':'D'] = 30
s[s>25] = 100
例:
df = pd.DataFrame([[1,2,3,4], [5,6,7,8], [9,10,11,12]], columns=list('ABCD'), index=list('XYZ'))
df['A'] = 100
df['B'] = df['B'] * 10
df['E'] = df['C'] + df['D']
df.loc[df['E']>10, 'E'] = 200 # 常用
df.loc['Y':'Z', 'C':'D'] = 666
例:
df = pd.read_excel('test.xlsx', index_col='num')
df['销售金额'] = df['单价'] * df['销售数量'] # 已知销售数量和单价,新增销售金额
apply()
def apply(self, func, axis=0, raw=False, result_type=None, args=(), **kwds):
df['单价']=df['单价'].apply(lambda x: x+3)
df['加分']=df['民族'].apply(lambda x: 5 if x!='汉' else 0) # 新增加分列,非汉族的加5分,x即单元格里的值
df['最终分数']=df['总分']+df['加分']
df['姓名字数']=df['姓名'].apply(len) # 只要是函数就行,如np.square平方根
df2=df.apply(lambda x:np.square(x) if x.name in ['x','y'] else x) # x.name是列名,因为默认axis=0
df2=df.apply(lambda x:np.square(x) if x.name in ['a','b'] else x, axis=1)
df['间隔']=df['结束日期'] - df['起始日期'] # 得出的数据带days,不是我们期望的,如7 days
df['间隔日期']=(df['结束日期'] - df['起始日期']).apply(lambda x: x.days)
+-*/算术运算df['列'].add()|.sub()|mul()|.div()|.floordiv()|pow()
另df['列'].radd()|rsub()|rmul()|rdiv()|rfloordiv()|rpow() # 反转方法,在用减法|除法|幂次方时会不一样,记着将fill_value=0带上
需注意的问题:
对空值的处理;
对除数为0的处理;
对空值的处理:
number +-*/ NaN = NaN # 大多数情况下会将空值替换为0再运算
NaN +-*/ number = NaN
将空值作为0:
fillna(0) # 方1,运算前提前将空值替换为0
add(fill_value=0) # +,方2
sub(fill_value=0) # -
mul(fill_value=0) # *
div(fill_value=0) # /
对除数为0的处理:
1 / 0 = inf # 等价于np.inf
-1 / 0 = -inf # 等价于-np.inf
0 / 0 = NaN
pandas.options.mode.use_inf_as_na = True # 将无穷大转为空
1 / 0 = NaN
-1 / 0 = NaN
例:
import pandas as pd
import numpy as np
df = pd.DataFrame([[1,2], [1, np.NaN], [np.NaN, 1], columns=['A','B'])
df['A']+df['B']
df['A']-df['B']
df['A']*df['B']
df['A']/df['B']
df['A'].add(df['B'], fill_value=0) # 将空值填充为0再计算,同df['A'].fillna(0)+df['B'].fillno(0)
df = pd.DataFrame([[1,0], [-1,0], [0,0], columns=['A','B'])
df['A'].div(df['B']) # inf|-inf|NaN
pandas.options.mode.use_inf_as_na = True
df['A'].div(df['B']) # NaN|NaN|NaN
例,Series的index不对齐的情况:
s1 = pd.Series([1,2], index=['a','b'])
s2 = pd.Series([10,20], index=['c','b'])
s1.add(s2) # 同pd.Series.add(s1, s2)
s1.add(s2, fill_value=0)
例,DataFrame运算:
df1 = pd.DataFrame([[1,2],[3,4]], columns=['A','B'], index=['X','Y'])
df1
df1.add(df1)
df2 = pd.DataFrame([[10,20],[30,40]], columns=['C','B'], index=['Z','Y'])
df1.add(df2)
df1.add(df2, fill_value=0)
例,MultiIndex情况:
df = pd.read_excel('jd_tb.xlsx', header=[0,1])
df
df.columns
df[('京东','销量')] + df[('淘宝','销量')]
df['京东'] + df['淘宝']
df_total = df['京东'] + df['淘宝']
df_total.columns = pd.MultiIndex.from_product([['总'], df_total.columns])
df_total
df.join(df_total)
排序sort_values()|sort_index()
def sort_values(self, by, axis=0, ascending=True, inplace=False, kind="quicksort", na_position="last", ignore_index=False):
参数:
axis=0 # 如果0那么by='列名',如果1那么by='行名'
ascending=True # 默认升序,False降序,结合by=['语文','数学']可以ascending=[True, False]第1字段升序第2个降序
inplace=True # 不创建新的对象,直接对原始对象修改;False对数据进行修改,创建并返回新的对象承载其修改结果
kind='quicksort' # quicksort|mergesort|heapsort
na_position='last' # first|last,默认缺失值排在最后
例:
df=pd.read_excel('test.xlsx', index_col='序号')
df.sort_index(inplace=True) # 按索引排序,已设置索引为“序号”;对于MultiIndex,df.sot_index(level='科目')
df.sort_values(by='语文', inplace=True, ascending=False)
df.sort_values(by=['语文', '数学', '英语'], inplace=True, ascending=[False, True, False])
连接查询(数据合并与重塑)
pd.concat() # 可沿一条轴将多个对象连接到一起(要搞清楚轴),用的最多
pd.merge() # 根据一个或多个键将不同的df中的行连接起来
df.join() # inner|outer
pd.merge():
inner join内连接|left join|right join;
类似sql里的join,将2个df共有的列连接起来,实际场景共有列一般是id,连接方式有inner默认|left|right|outer全外连接;
参数:
how # 数据融合的方法inner|left|right|outer
on # 用来对齐的列名,一定要保证左表和右表存在相同的列名
left_on # 左表对齐的列,可以是列名,也可以是df同长度的arrays
right_on # 右表对齐的列,可以是列名
left_index # 将左表的index用作连接键
right_index #
suffixes # 后缀名,用于左右df中存在重名列,结果区分的方式,suffixes=['_l','_r']
copy # 默认True,将数据复制到数据结构中,设置为False可提高性能
例,pd.merge(df1,df2, on='name', how='inner'):
df1=pd.DataFrame({'姓名':['叶问','李小龙','陈真','叶问','叶问','李小龙'],'出手次数1':np.arange(6)})
df2=pd.DataFrame({'姓名':['黄飞鸿','李小龙','陈真'],'出手次数2':[1,2,3]})
pd.merge(df1,df2) # inner,同pd.merge(df1,df2, on='姓名', how='inner')
pd.merge(df1,df2, on='姓名', how='left') # 另right|全外连接outer
例,pd.merge(df1,df2, on=['name','class'], how='inner'):
df1=pd.DataFrame({'name': ['zhang3','zhang3','wang5'], 'class':['1class','2class', '1class'], 'score': [10,20,30]})
df2=pd.DataFrame({'name':['zhang3','zhang3','wang5','wang5'],'class':['1class','1class','1class','2class'],'score':[]})
pd.merge(df1,df2, on=['name','class']) # inner
pd.merge(df1,df2, on=['name','class'], how='left') #
例,pd.merge(df1,df2, left_on='name', right_index=True, how='inner'):
df1=pd.DataFrame({'name':['zhang3','li4','wang5','li4'],'count':range(5)})
df2=pd.DataFrame({'data':[10,20],index=['zhang3','li4'})
pd.merge(df1,df2, left_on='name', right_index=True) # how='inner'
df1.join(df2)
join合并,默认横向,不推荐用,推荐pd.merge();
将2个df中不同的列索引合并成一个df,同merge参数,不过join默认左外连接how=left;
def join(self,other,on=None,how='left',lsuffix='',rsuffix='',sort=False)
pd.concat()
def concat(objs, axis=0, join='outer', ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=False, copy=True):
参数:
objs=[] # 合并的对象集合,可以是Series|DataFrame
axis=0 # 合并方法,默认按行索引(纵向|列对齐)合并,1列索引(横向|行对齐)
join='outer' # 默认outer并集,另inner,只有这2种
join_axes # 按哪个对象的索引保存,指定根据哪个轴来对齐数据,如pd.concat([df1,df2], axis=1, join_axes=[df1.index])(根据df1表对齐数据,保留指定的df1表的轴,将df2的表与之拼接)
ignore_index=False # 忽略原index,ignore_index=True(用于两个表的index没有实际含义,合并的两个表根据列字段对齐然后合并,最后重新整理一个新的index)
keys=None # 为原始df添加一个键,用于识别新表中的数据属于哪个原始表,几个表合并就写几个如pd.concat([df1,df2,df3],keys=['t1','t2','t3'])或pd.concat({'t1':df1,'t2':df2,'t3':df3})
sort=True # pd默认用index排序
例:
s1=pd.Series([0,1,2],index=['A','B','C'])
s2=pd.Series([3,4],index=['D','E'])
pd.concat([s1,s2]) # 默认按行索引axis=0合并
pd.concat([s1,s2], axis=1)
Series|DataFrame的join()|append()
df1.append(df2) # 默认按列对齐(将两个表行记录合并)
df1.append(s2, ignore_index=True) # 在df中加入新的行
df1.append([df2,df3], ignore_index=True) # df1,df2,df3的列字段不同要合并
分组与聚合df.groupby()
count # 分组中非NA值的数量
sum # 非NA值的和
mean # 非NA值的平均值
median # 非NA值的算术中位数
std|var # 无偏标准差和方差(分母为n-1)
min|max # 非NA值的min|max
prod # 非NA值的积
first|last # 非NA值的first|last
def aggregate(self, func, axis=0, *args, **kwargs):
使用指定轴上的一个或多个操作进行聚合,agg函数一般与groupby使用,agg是基于列的聚合操作,groupby是基于行的;
参数:
func # str|list|dict,{'行或列': func}
例:
for (i, j), group in df.groupby(['city', 'district']):
print(i, j) # print(group)
df=pd.read_excel('test.xlsx', index_col='city')
df2=df.groupby(['city', 'district'])[['number_of_people',]].sum() #
d = {'Jan': 'count', 'Feb': sum, 'Mar': max, 'Apr': 'mean'} # 内建函数直接写,非内建函数要加引号
df2=df.groupby('shop').agg(d)
df2.sum()
d = {'Jan': '1quarter', 'Feb': '1quarter', 'Mar': '1quarter', 'Apr': '2quarter'} # 对应关系
df.set_index('店号')
df2=df.groupby(d, axis=1)
df2.sum()
df2=df.groupby(len).sum()
df=pd.read_excel('test.xlsx', index_col='店号')
cities=['BJ','BJ','SH','BJ','TJ','BJ']
df2=df.groupby([len,cities]).sum()
df=pd.read_excel('test.xlsx', index_col=[0, 1]) # 0班级1学号,将0列和1列设为索引,其余列将全是数值型才能做聚合操作
df2=df.groupby(level='班级').mean() # 求各班的语文|数学平均分,
df=pd.read_excel('test.xlsx', header=[0,1])
l1=['1季度','1季度','1季度','2季度','2季度']
l2=['1月','2月','3月','4月','5月']
mi=pd.MultiIndex.from_arrays([l1,l2], names=['季度','月份'])
df2=pd.DatatFrame(df, columns=mi)
df2=df2.groupby(level='季度', axis=1).sum()
print(df2)
df2=df.groupby(df.姓名.str[0])[['Chinese','Math','English']].sum() # 按姓聚合计算
df2=df.groupby([df.姓名.str[0], df.name.str[1]])[['Chinese','Math','English']].sum()
df2=df.groupby(df.班级.isin(['1class', '2class']))[['Chinese','Math','English']].sum() # 在1班、2班里,取非用~df.班级.isin(['1class','2class'])
df2=df.groupby(df.时间.dt.year)[['Chinese','Math','English']].sum() # .dt是列为时间类型的函数,df.groupby([df.时间.dt.year, df.时间.dt.month])
df2=df.pipe(pd.DataFrame.groupby, '班级').sum()
数据透视表pd.pivot_table()|交叉表pd.crosstab()
def pivot_table(
data,
values=None,
index=None,
columns=None,
aggfunc="mean",
fill_value=None,
margins=False,
dropna=True,
margins_name="All",
observed=False,
) -> "DataFrame":
参数:
values=None # 在结果透视的行上进行分组的列名或其它分组键(透视表里显示哪些列)
index=None # 需要聚合的列名(按哪个索引进行透视),默认聚合所有列
columns=None # 在结果透视表的列上进行分组的列名或其它分组键(增加透视表的列)
aggfunc='mean' # str|list,聚合函数或函数列表,可以是groupby里的任意有效函数
fill_value=None # 在结果表中替换缺失值
dropna=True # True将不含所有条目中Na的列
margins=False # True添加行|列小计和总计,不是简单的求和而是与aggfunc的规则相同
例:
df2=pd.pivot_table(df, index=['部门','销售人员'])
df2=pd.pivot_table(df, index=['部门','销售人员'], values=['数量', '金额'])
df2=pd.pivot_table(df, index=['部门','销售人员'], values=['数量', '金额'], columns='所属区域', aggfunc=[sum, np.mean]) # aggfunc=[np.sum, np.mean]
def crosstab(
index,
columns,
values=None,
rownames=None,
colnames=None,
aggfunc=None,
margins=False,
margins_name: str = "All",
dropna: bool = True,
normalize=False,
) -> "DataFrame":
例:
df2 = pd.crosstab([df.日期.dt.month, df.所属区域], df.部门, margins=True)
pandas中使用excel的vlookup
df1 = pd.read_excel('test.xlsx', sheet_name='花名册')
df2 = pd.read_excel('test.xlsx', sheet_name='花名册')
res = pd.merge(df1, df2.loc[:, ['学号','总分']], how='left', on='学号')
res_总分 = res.总分
res = res.drop('总分', axis=1)
res.insert(0, '总分', res_总分)
print(res)
数据处理三板斧map()|apply()|applymap()|pipe()
要将自定义或其他库的函数应用于pandas对象,有3个重要的方法,使用适当的方法取决于函数是否期望在整个DataFrame行或列或元素上进行操作:
pipe() # 表式函数应用,可通过将函数和适当数量的参数作为管道参数来执行自定义操作,从而对整个DataFrame执行操作
apply() # 行列函数应用,沿DataFrame或Panel的轴应用任意函数,它与描述性统计方法一样,apply()方法使用一个可选的axis参数
applymap() # 元素函数应用,和Series上的map()类似,接受任何py函数,该函数要求能够接受单个值并返回单个值
def pipe(self, func, *args, **kwargs):
专门用于对Series和DataFrame操作进行流水线改造的api,作用是将嵌套的函数调用过程改造为链式过程;
参数:
func # 传入作用于s|df的函数
例:
df2=df.pipe(pd.DataFrame.groupby, '班级').sum()
pip
def map(self, arg, na_action=None):
是Series对象的函数(对单个列操作,DataFrame的单行和单列可看作是1个Series对象),将一个自定义函数作用于Series对象的每个元素;
区别于df.replace();
如果自定义函数需传1个参数用s.map(),如果自定义函数有多个参数用df.apply()
例:
d = {'男': '先生', '女': '女士}
df['称呼'] = df['性别'].map(d) # 同.map(lambda x: '先生' if x=='男' else '女士')
def apply(self, func, axis=0, raw=False, result_type=None, args=(), **kwds):
将一个自定义函数作用于DataFrame的行或列;
例:
df['单价']=df['单价'].apply(lambda x: x+3)
df['加分']=df['民族'].apply(lambda x: 5 if x!='汉' else 0) # 新增加分列,非汉族的加5分,x即单元格里的值
df['最终分数']=df['总分']+df['加分']
df['姓名字数']=df['姓名'].apply(len) # 只要是函数就行(内建或自定义),如np.square平方根
df2=df.apply(lambda x:np.square(x) if x.name in ['x','y'] else x) # x.name是列名,因为默认axis=0
df2=df.apply(lambda x:np.square(x) if x.name in ['a','b'] else x, axis=1)
df['间隔']=df['结束日期'] - df['起始日期'] # 得出的数据带days,不是我们期望的,如7 days
df['间隔日期']=(df['结束日期'] - df['起始日期']).apply(lambda x: x.days)
def cus_func(x, v):
retrun x+v
df['语文']=df['语文'].apply(cus_func, args=(-3,)) # 自定义函数需传多个参数
df2 = df[['语文','数学','英语']].apply(sum, axis=0)
df['总分'] = df[['语文','数学','英语']].apply(sum, axis=1) # 每个学生的这三门课的总分
df['bmi'] = df.apply(lambda x: x['体重']/x['身高']**2)
def applymap(self, func) -> "DataFrame":
将自定义函数作用于DataFrame的所有元素;
例:
df2 = df.applymap(lambda x: '%.2f'.format(x))
数据自动填充
例:
def accumulation_month(arg_dt, arg_month):
year=arg_month // 12
month=arg_dt.month + arg_month % 12
if month != 12:
year += month // 12
month %= 12
return datetime.date(arg_dt.year + year, month, arg_dt.day)
df=pd.read_excel('test.xlsx', skiprows=8, usecols='F:I', dtype={'num': str, 'gender': str, 'dt': str}) # 需要填充的列必须是str类型
start_dt=datetime.date(2021,2,20)
for i in df.index:
df['num'].at[i]=i+1
df['gender'].at[i]='male' if i%2==0 else 'femal'
# df['dt'].at[i]=start_dt+datetime.timedelta(days=i)
# df['dt'].at[i]=datetime.date(start_dt.year+i,start_dt.month,start_dt.day)
df['dt'].at[i]=accumulation_month(start_dt, i)
df.set_index('num', inplace=True)
print(df)
df.to_excel('test1.xlsx')
数据转置|计算的环比同比
转置df.values.T
df2 = pd.DataFrame(df.values.T, index=df.columns, columns=df.index)
环比,当月比上月
df = pd.read_excel('test.xlsx', 'Sheet1')
上月 = df.销售金额.shift()
df['环比增长金额'] = df.销售金额 - 上月
df = pd.read_excel('test.xlsx', 'Sheet2')
df2 = df.sort_values(['城市', '月份']).groupby('城市').apply(lambda x: x.金额 - x.金额.shift())
同比,在excel中用“数据透视表”做
df2 = pd.pivot_table(df, index='店号', values='金额', columns=df['日期'].dt.year, aggfunc='sum')
df2['同比'] = (df2[2019]-df2[2018])/df2[2018]
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~