pandas数据分析处理52个常用技巧
不凡 Lv2

导入工具包

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# pandas 和numpy是两个基础的工具包
import numpy as np
import pandas as pd
# matplotlib seaborn是作图工具包
import matplotlib.pyplot as plt
import seaborn as sns
# 通过os设置默认路径
import os
os.chdir('C:/Users/用户/Desktop/') # 桌面的路径
# 图表中文显示问题
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
# 不显示预警
import warnings
warnings.filterwarnings('ignore')

spyder中快捷方式

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
# 注释、取消注释
Ctrl+1
# 块注释 / 取消块注释
Ctrl+4/5
# 从当前光标所在行开始执行
F9

读取excel文件

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
# 读取文件
df = pd.read_excel('文件.xlsx')
# 读取文件同时筛选需要的列
df = pd.read_excel('文件.xlsx')[['','']] # 读取并筛选几列
# 读取特定的工作表
df = pd.read_excel('文件.xlsx',sheet_name='明细') # 读取某个sheet表
# with方法读取
with pd.ExcelFile('path_to_file.xls') as xls:
df1 = pd.read_excel(xls, 'Sheet1')
df2 = pd.read_excel(xls, 'Sheet2')

读取csv和txt文件

折叠代码块PYTHON 复制代码
1
2
# 分隔符: \s 表示空白字符; \s+多个空白字符; \r回车; \n换行; \t水平制表符; \v垂直制表符
df = pd.read_csv('文件.txt',sep='\s+',error_bad_lines=False)

批量读取同一文件夹下文件1

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
for root, dirs, files in os.walk('.',topdown=False):
print(files)
num = len(files) # 获取文件个数
data = pd.DataFrame() # 定义一个空的dataframe
# 遍历所有文件
for i in range(num):
datai = pd.read_excel('./%s' %files[i])
datai_len = len(datai)
data = data.append(datai) # 添加到总的数据中
print('文件%i列, 第%i个表,读取%i行数据,名称:%s'%(len(data.columns),i,datai_len,files[i])) # 查看是否全部读取,格式是否出错

data.reset_index(drop=True,inplace=True)

批量读取同一文件夹下的文件2

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 导入工具包
import pandas as pd
import numpy as np
import os

# 路径
path = 'd:/文件路径/'

# 文件列表
files = []
for file in os.listdir(path):
if file.endswith(".csv"):
files.append(path+file)

# 定义一个空的dataframe
data = pd.DataFrame()

# 遍历所有文件
for file in files:
datai = pd.read_csv(file,encoding='gbk')
datai_len = len(datai)
data = data.append(datai) # 添加到总的数据中
print('读取%i行数据,合并后文件%i列, 名称:%s'%(datai_len,len(data.columns),file.split('/')[-1]))
# 查看是否全部读取,格式是否出错
# 重置索引
data.reset_index(drop=True,inplace=True)

批量读取同一文件夹下的文件3

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 循环读取数据
n = 1
for file in files:
with open(file, 'r',encoding='gbk') as f_input:
lisi= []
for line in f_input:
lisi.append(list(line.strip().split('|')))

datai = pd.DataFrame(lisi)
datai2 = guolv(datai)
data = data.append(datai2)

print('读取第%i个文件,件名%s,文件%i行,文%i列.处理后文件%i行,%i列' %(n,file,datai.shape[0],datai.shape[1],datai2.shape[0],datai2.shape[1]))
n = n + 1

数据导出为excel,同一工作簿

折叠代码块PYTHON 复制代码
1
2
3
with pd.ExcelWriter('文件.xlsx') as writer:
df1.to_excel(writer, sheet_name='文件1')
df2.to_excel(writer, sheet_name='文件2')

数据导出为excel,分组导出到同一工作簿

折叠代码块PYTHON 复制代码
1
2
3
writer = pd.ExcelWriter('文件.xlsx')
for name , group in df.groupby('名称'):
group.to_excel(writer,sheet_name=name,index=False)

数据导出为excel,分组导出到不同的工作簿

折叠代码块PYTHON 复制代码
1
2
for name , group in df.groupby('名称'):
group.to_excel(name+'.xlsx',index=False)

获取当前时间

折叠代码块PYTHON 复制代码
1
2
import time
tim = time.strftime("%Y-%m-%d%H%M%S", time.localtime())

保存图片分辨率设置

折叠代码块PYTHON 复制代码
1
plt.savefig('名称.png',dpi=150)  

数据查看

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
df.describe()   # 描述统计
df.info() # 基本信息
df.dtypes # 列格式类型
df.head(2) #前n行
df.tail(2) #后n行
df.shape #维度
df.index #索引
df.columns #列名
df.sample(10) #随机抽样
df.resample()  #随机抽样

行列处理(删除、排序)

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 删除列
del df['变量名']
df.drop('变量名',axis=1,inplace=True)
# 删除行
df.drop('c')
# 更改列名
df.columns= ['var1','var2','var3'] # 列名的个数 = 字段个数
df.rename(columns = {'名称前':'名称后'},inplace=True) # columns 不能少
# series中改列名
s.rename('名称',inplace=True)
# 调整列的顺序
df1 = df1[['var1','var2','var3']]
# 调整行的顺序
df2 = df1.reindex(['a','b','c','d','e']) # 返回一个新的DataFrame,按新的索引进行排序

缺失值(查看、替换、计数)

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 判断是否是缺失值
df.isnull() #不能省略括号
df.notnull()
# 计算缺失值个数
s.isnull().value_counts()
# 每列缺失值个数
df.isna().sum() # 缺失值个数

# 填充缺失值
df['A'].fillna('缺失数据',inplace=True)
data1.fillna(method='pad') # 类似于excel中用上一个单元格内容批量填充

# 删除指定列包含缺失值的行
data.dropna(subset=["C"],inplace=True) # []不能少
data.dropna(how="all") # 删除全为空的行
data.dropna(thresh=2) #删除有效数据小于2的数据

# 缺失值个数并排序
df.isnull().sum().sort_values(ascending=False).head()

重复值(查看、删除)

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 不重复项
df['A'].unique()
df['A'].nunique() #查看不重复值个数
df['A'].unique().tolist() # 转list
df['A'].value_counts() # 计数
# 去重
set(data2['名称'])

# 查看重复项,返回True False
df.duplicated()
# 查看重复的数据
data4 = data3[data3.duplicated(subset='var1',keep=False)]

# 删除重复项
df.drop_duplicates(['var'],inplace=True)
# 按两列去重
data.drop_duplicates(subset=['A','B'],keep='first',inplace=True)
# 分组计算不重复项个数
result = df.groupby(['var1','var2']).agg({'var3':'nunique','var4':['min','max']})

修改格式((格式转换, 百分比, 格式判断))

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
# 改变列的格式(文本型数值改成数值型数值)
df['var1'] = df['var1'].astype('int') # errors = 'ignore'
df['var1'] = df['var1'].astype(np.float)
# 多列转换
df[['user_id','merchant_id','coupon_id']]=df[['user_id','merchant_id','coupon_id']].astype(str)
df.infer_objects() # 根据数据特征自动转换

# 百分比格式
data['B_per%'] = data['B_per'].apply(lambda x: '%.2f%%' % (x*100))

# 判断格式,是否为字符串
data['var'].apply(lambda x:isinstance(x,str))

普通筛选

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# loc筛选:选择符合条件的行
df.loc[df["grade"] == "B"].head()

# 选择符合条件的行和特定的列
df.loc[df["grade"] == "B", ["member_id", "grade"]].head()
# 选择符合条件的行和特定的列,并排序
df.loc[df["grade"] == "B", ["loan_amnt", "grade"]].sort(["loan_amnt"])
# 多条件筛选
df.loc[[(df["gradd"]=="B") & (df["loan_amnt"]>5000), ["member_id", "term" ]].head()
# 反选
data[~((data.发布时间.isnull()) & (data.实际首试日期 < '2018-11-1'))]
# 反转行
df.iloc[::-1, :]

逻辑判断后筛选

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# isin筛选
df["A"].isin([1,2,3])
# 多条件
df[(df.AAA <= 6) & (df.index.isin([0, 2, 4]))]
# loc和isin组合 
df.loc[df['sepal_length'].isin([5.8,5.1])]
# 字符串isin
df.loc[df['grade'].isin(['北京','上海'])]
# 字符串开头
df[df['A'].str.startswith('北京')]

# contains筛选
df[df['商品名称'].str.contains("四件套")]
# 多个筛选
df_re =df[df['公司'].str.contains('公司A||公司B')]
# 筛选含特殊字符的
df[df['产业线'].str.contains('\?')]
# 多条件筛选
data[(data['var1'].str[0] == 'M')&(data['var2'].apply(lambda x : str(x)[0] == '8'))]

# 索引特殊用法
df[[i.endswith('A') for i in df.index]]

# 按字符串长度筛选
data = df[df['名称'].str.len()>5]

# 按字符串开头筛选
df[df['名称'].str[0] == 'M']

# 筛选列
data = data.loc[:,~(data.columns.str.contains('集团'))]

# 筛选前几个最大值
data = df.iloc[df['名称'].nlargest(3).index]

# 筛选由汉字开头的数据
df = df[df['名称'].str.contains(r'^[\u4e00-\u9fa5]')]

# 日期不是索引时, 按日期筛选
data[data['时间'].apply(lambda x: x.year == 2019)]
data[data['时间'].apply(lambda x: x.strftime('%Y%m')=='202008')]

分组后筛选

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 分组后筛选前2个
df2 = df1.groupby(['class']).head(2)

# 分组后筛选第2条或者倒数第2条数据
df1.groupby('class').apply(lambda i:i.iloc[1] if len(i)>1 else np.nan)
df1.groupby('class').apply(lambda i:i.iloc[-2] if len(i)>1 else np.nan)

# 分组后按条件筛选
data.groupby('var1').filter(lambda x: len(x[x['var2']=='A'])>=1)
data.groupby('公司编码').filter(lambda x:len(x)!=3)

# groupby筛选方法1(先分组,然后筛选另一个变量中最小值)
df.loc[df.groupby('AA')['BB'].inxmin()]
#groupby筛选方法2:(先排序,分组,然后筛选每一组中的第一个)
df.sort_values(by='BB').groupby('AA',as_index=False).first()
# groupby筛选方法3:groupby与apply结合
df.groupby('aa').apply(lambda x : x['BB'][x['cc'].idxmax()]

# 分组并排序
df[['A','B']].groupby('A').mean().sort_values('B',ascending=False).head()

替换

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 单个替换
df['判断'].replace(['B','C'],np.nan,inplace=True) #支持正则表达式
# 多个替换
data['var'].replace(['A','B'],['a','b'],inplace=True)
# loc原地替换
df1.loc[df['sex']=='female', 'sex'] = 1
df1.loc[df['sex']=='male', 'sex'] = 0

# 字典
df.replace({'female':1, 'male':0})
# 适合二分法
df1['sex'] = df1['sex'].map(lambda x:1 if x=='female' else 0)
# apply
df_zb['var'] = df_zb['var'].apply(lambda x: x[:-1] if x[-1].isalpha() else x)
data3['var'] = data3['var'].apply(lambda x: x[:-1] if x[-1] == 's' else x)

# np.where
data['var'] = np.where(data['var'] == ' ',0,data['var'])

字符串处理

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
print('我的名字是%s,今年%i岁,体重%.2f'%('小明',20,70.1))
# 去除空格,改变大小写
df['term'] = df['term'].map(str.strip) #去除左右两边的空格,strip后面是否带括号
df['term'] = df['term'].str.strip()
df['term'] = df['term'].map(str.lstrip) #去除左边的空格
df['term'] = df['term'].map(str.rstrip) #去除右边的空格
df['term'] = df['term'].map(str.upper) # 改成全部大写
df['term'] = df['term'].map(str.lower) # 改成全部小写
df['term'] = df['term'].map(str.title) # 改成首字母大写

# 去掉所有空格
data = data.applymap(lambda x: x.strip() if isinstance(x,str) else x)

字符串判断

折叠代码块PYTHON 复制代码
1
2
3
4
# 判断是否为某一特定格式
df['emp_length'].apply(lambda x: x.isalpha()) #是否为字母
df['emp_length'].apply(lambda x: x. isalnum ()) #是否全未数字或者字母
df['emp_length'].apply(lambda x: x. isdigit ()) #是否为数字

字符串拆分

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
s.str.split('_')  # 拆分,结果是列表
s.str.split('_').str.get(1) # 拆分后取第一个,可用于生成新变量
s.str.split('_').str[1] # 拆分后取第一个,可用于生成新变量
s.str.split('_', expand=True) # 拆分,并展开成多列
s.str.split('_', expand=True, n=1) # 按第一个拆分
s.str.rsplit('_', expand=True, n=1) # 按最后一个拆分
data['var'] = data['var'].str.split('?',expand=True)[0]

索引

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 把列变成索引
df.set_index('时间',inplace=True, drop = False)
df.set_index(['r','s'], inplace = True) # r为一级,s为二级

# 取消层次化索引,将索引变回列
df.reset_index(inplace=True)
df.reset_index(drop=True,inplace=True,level = None)

# 按索引排序
df.sort_index(inplace=True,ascending=False)

# 更新索引(行、列都可以修改)
df2 = df1.reindex(['a','b','c','d','e']) # 返回一个新的DataFrame,按新的索引进行排序
df2 = df1.reindex(['a','b','c','d','e'], fill_value=0)

# 多级索引问题(索引可以在行,也可以在列)
df.index.names=['类型','供应商'] # 取名称
df.columns.names=['类型','日期'] # 取名称
df1 = df.swaplevel('类型','日期',axis=1) #调整多级索引次序
df1 = df.sort_index(level=0, axis=1, ascending=True,sort_remaining=False) # sort_remaining 默认是True
df1 = df.sum(axis=1,level='类型') # 通过索引对多列进行求和

排序

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
# na_position对NaN值的处理方式,可以选择first和last两种方式
df.sort()
# 单列排序
df.sort(["loan_amnt"],ascending=False) # 降序
# 多列进行排序,加入一个列表
df.sort(["loan_amnt","int_rate"],ascending=False)
# 升序排列后选择前10
df.sort(["loan_amnt"],ascending=True).head(10)
# 自定义排序
df.sort_values(by=['日期','类型','距离'],ascending=True,inplace=True,na_position = 'last')
# 索引排序
df.sort_index(inplace=True)

日期

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# 设置成日期格式
df['创建日期'] = pd.to_datetime(data_final['创建日期'],format='%Y/%m/%d')
# 设置为日期索引
df.set_index('订单提交时间',inplace=True)

# 日期索引排序
df.sort_index(inplace=True,ascending=False)
# 日期索引的筛选
df_2019 = df['2019'] # 日期索引可以直接这样筛选
df['2019-01'] #按月筛选
df['2019-03-12':'2019-03-12'] #筛选某一天数据

# 改变显示频率(只针对日期索引)
df = df.to_period('M') # 针对索引,关键步骤 Q 季度 Y年 D天

# 计算时间间隔
data['间隔天数'] = list(map(lambda x: x.days, pd.to_datetime('today') - data['生产时间']))
df['天数'] = df['天数'].apply(lambda x: x.days)

# 单独表示间隔天数
from datetime import timedelta
aDay = timedelta(days=1)

# 时间对象格式化
df['DATE'] = [datetime.strftime(x,'%Y-%m-%d') for x in df['DATE']]

# 时间分组后计算
final = data.groupby(data['订单时间'].apply(lambda x: x.strftime('%Y%m')))['总价'].sum()/10000
data.groupby(data['日期'].apply(lambda x: datetime.strftime(x,'%Y-%m-%d')))['var'].count()
data.set_index('日期').groupby('供应商')['数量'].rolling('7D').sum().reset_index()
final1 = data.groupby([data.to_period('Q').index,'var']).apply(lambda g: np.average(g['var2'], weights=g['模次'])).reset_index()

# 当前时间
import time
starttime = time.time()

# 当前日期
tim = time.strftime("%Y-%m-%d%H%M%S", time.localtime())

# pd.date_range 时间戳 pd.period_range 时间周期 pd.timedelta_range 时间间隔
datelist = pd.date_range('2020/11/21', periods=5)
datelist = pd.date_range('2020/11/21', periods=5,freq='M')
# 生成的数据是每月月初
index= pd.date_range('2019/02/01', periods=23,freq='MS')
pd.date_range('2017-01-01 01:00:00', '2017-01-01 02:00:00', freq= '5min')

# 当前日期前3天
import pandas as pd
from datetime import datetime
import time
lis = pd.date_range(end='2021-4-21',periods=3)
str_lis = [datetime.strftime(x,'%Y-%m-%d') for x in lis]
lis = pd.date_range(end=time.strftime("%Y/%m/%d"),periods=3)
str_lis = [datetime.strftime(x,'%Y-%m-%d') for x in lis]

判断是否为假期

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
import datetime
import chinese_calendar
demo_time = datetime.date(2018, 10, 2)
# 判断是否是节假日
data_is_holiday = chinese_calendar.is_holiday(demo_time) # True
# 判断某日是否工作日
data_is_workday = chinese_calendar.is_workday(demo_time) # False

数据分组

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
# 方法1
data['for_m'] = pd.cut(data['fortune_x'],[0,50,70,500],labels = ['财低','财中','财高'])
# 方法2
df = pd.DataFrame({'value': np.random.randint(0, 100, 20)})
labels = ["{0} - {1}".format(i, i + 9) for i in range(0, 100, 10)]
df['group'] = pd.cut(df.value, range(0, 105, 10), right=False, labels=labels)

多表合并

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
# 默认纵向连接,产生新的坐标轴   
df = pd.concat([df1,df2],ignore_index=True)

# merge 合并
pd.merge(left, right, left_on="lkey", right_on="rkey",suffixes=("_left", "_right"))
pd.merge(df, df, left_on=['','',''], right_on=['','',''], suffixes=('',''))

# append 表头一致的多张表,进行连接(上下连接)
df1.append(df2).append(df3)

# combine_first
数据填补.有两张表left和right,一般要求它们的表格结构一致,数据量也一致,使用right的数据去填补left的数据缺漏, 如果在同一位置left与right数据不一致,保留left的数据
df1.combine_first(df2)

常用函数

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
count()非空观测数量  
sum()所有值之和
mean()所有值的平均值
median()所有值的中位数
mode()值的模值
std()值的标准偏差
var()方差
min()所有值中的最小值
max()所有值中的最大值
abs()绝对值
prod()数组元素的乘积
cumsum()累计总和
cumprod()累计乘积
skew()偏斜
kurt()峰度
quantile()分位数
apply()通用申请
cov()协方差
corr() 相关系数

描述性统计

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
df.describe(include=['object'])    #object - 汇总字符串列  number - 汇总数字列 all - 将所有列汇总在一起(不应将其作为列表值传递)
df.describe().round(2) # 只保留两位小数
df.describe().round(2).T #只保留两位小数并转置
df.groupby('性别').describe().unstack()
df.groupby('性别')['身高'].describe().unstack()
df.round(3) # 数据可以取消科学计数法?
df = df.round(0) # 都改为整数
# 保留2位小数
df['a']=df['mean'].round(decimals=2)
df['b']=df['mean'].map(lambda x:("%.2f")%x)
df['c']=df['mean'].map(lambda x:format(x,".2%"))
description = [data.min(), data.max(), data.mean(), data.std()] # 依次计算最小值、最大值、均值、标准差
description = pd.DataFrame(description, index = ['Min', 'Max', 'Mean', 'STD']).T # 将结果存入数据框
print('描述性统计结果:\n',np.round(description, 2))

数据预览

折叠代码块PYTHON 复制代码
1
2
3
4
5
# 在cmd中安装
pip install pandas-profiling
import pandas_profiling
pro = pandas_profiling.ProfileReport(data1)
pro.to_file('output_file.html')

显示百分比

折叠代码块PYTHON 复制代码
1
2
# 元素变化百分比 每个元素与其前一个元素进行比较,并计算变化百分比
df.pct_change()

协方差

折叠代码块PYTHON 复制代码
1
2
3
# 协方差,cov用来计算序列对象之间的协方差
s1.cov(s2)
df['a'].cov(df['b'])

相关性

折叠代码块PYTHON 复制代码
1
2
3
# 相关性,pearson(默认),spearman和kendall之间的相关性
df['a'].corr(df['b'],method ='spearman')
print (frame.corr())

排名

折叠代码块PYTHON 复制代码
1
2
3
4
s.rank() 或者 df.rank()  
# (axis=0)或列(axis=1)
# ascending=True 正向排名或者反向排名
# method (average :并列组平均排名,min :组中最低排名,max :组中最高等级,first :按在数组中出现的顺序分配等级)

分组计算

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 多组运算
df.groupby(['班级','性别'])['身高'].agg([np.sum,np.mean,np.std])
df.groupby(['班级','性别']).agg({'身高':['min'],'体重':['max']})
df.groupby('flee').agg({'身高': [np.median, np.mean], 'signs': np.mean})
df.agg({'A':np.sum,'B':np.mean}) # 对不同列进行不同的计算
df[['A','B']].agg([np.sum,np.mean,np.min]) # 对多个变量进行多种计算

# 时间分组 ,先用pd.to_datetime(字段,格式)将某一列转成日期格式
df.groupby(df['生日'].apply(lambda x:x.year)).count()
# 分组后选第一个,一般数据先排序
df.groupby(df['生日'].apply(lambda x:x.year),as_index=False).first() # Tail(n=1) head()
# 找到每组中只有一个数据的
df.groupby(df['生日'].apply(lambda x:x.month),as_index=False).filter(lambda x: len(x)==1)
data2.groupby('var').filter(lambda x:len(x)>=10)
data.groupby(data.index.year)['年龄'].mean()

# 加权平均
final3_1 = data_jiep.groupby(['产业线','模号']).apply(lambda g: np.average(g['平均节拍'], weights=g['模次'])).reset_index()

# groupby作图
data.groupby('race')['flee'].value_counts().unstack().plot(kind='bar', figsize=(20, 4))
data.groupby('flee')['age'].plot(kind='kde', legend=True, figsize=(20, 5))

# groupby中的几个函数
# 累计
df.groupby('key').aggregate('min', np.median, max)
# 过滤
df.groupby('key').filter(某个函数)
# 转换
df.groupby('key').transform(lambda x: x- x.mean())

#通过某一个字段分组后,选另一个字段的最小值,构成的数据
df = pd.DataFrame({'AAA': [1, 1, 1, 2, 2, 2, 3, 3],'BBB': [2, 1, 3, 4, 5, 1, 2, 3]})
df.loc[df.groupby("AAA")["BBB"].idxmin()]
# 按照一个字段排序,另一个字段分组,选取第一个
df.sort_values(by="BBB").groupby("AAA", as_index=False).first() #重新设置索引

# transform后数据大小不变
df["Order_Total"] = df.groupby('order')["ext price"].transform('sum')

result0 = data1.to_period('Q').groupby(level=0).apply(lambda x :len(x['var'].unique().tolist()))

交叉表

折叠代码块PYTHON 复制代码
1
result1 = pd.crosstab(data.index,data['产业线'],margins=True)

数据透视表

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
df.pivot_table('价格',index='产地',columns='类别',aggfunc='max',margins=True,fill_value=0,margins_name='合计')

# 用字典形式,可不用values参数
df.pivot_table(index='sex', columns='class', aggfunc={'surviced':'sum', 'fare':'mean'})

result = data.pivot_table(index=data3.to_period('M').index,columns= '是否异常',values='模号', aggfunc='count')

result1 = data.pivot_table(index= 'var1',columns=data['var3'].apply(lambda x: x.strftime('%Y')),
aggfunc='count',values='var2')

窗口函数

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
#索引需要为日期 对于明细数据,计算固定大小区域的指标
s = pd.Series(np.random.randn(1000),index=pd.date_range('1/1/2000', periods=1000))
s = s.cumsum()
r = s.rolling(window=60)
# window:移动窗口的大小
# min_periods:需要的非空数据点的阈值(否则结果为NA)
# center:布尔值,是否将标签设置在中间(默认为False)

df['数量_re'] = df['数量'].rolling('7D').sum()

data1 = data.set_index('入库日期').groupby('供应商')['入库量'].rolling('7D').sum().reset_index()

标准化

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 当越小越好时
df['var_nor'] = (df['var'].max() - df['var']) / (df['var'].max() - df['var'].min())
# 当越大越好时
df['var_nor'] = (df['var'] - df['var'].min()) / (df['var'].max() - df['var'].min())
# 当中值为好是
df['var'] = np.abs(df['var']-标准值)
df['var_nor'] = (df['var'].max() - df['var']) / (df['var'].max() - df['var'].min())

# 可以写成通用函数
def f2(data,col):
col_name = col + '_nor'
data_gp = data.groupby('类别').mean()
data_gp[col_name] = (data_gp[col] - data_gp[col].min() ) / (data_gp[col].max() - data_gp[col].min() )
return data_gp

去除异常值

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
def f2(data,col):
q1 = data[col].quantile(q=0.25)
q3 = data[col].quantile(q=0.75)
iqr = q3 - q1
t1 = q1 - 3*iqr
t2 = q3 + 3*iqr
return data[(data[col]>t1)&(data[col]<t2)][['类别',col]]

正态分布

折叠代码块PYTHON 复制代码
1
2
data_norm = pd.DataFrame({'正太分布':np.random.normal(loc=60,scale=15,size=10000)})
data_exp = pd.DataFrame({'指数分布':np.random.exponential(scale=15,size=10000)+45})

随机选择

折叠代码块PYTHON 复制代码
1
df['strategy'] = np.random.choice([1,2,3],99)

行列求和

折叠代码块PYTHON 复制代码
1
2
3
4
# 增加列合计
df['合计'] = df.sum(axis=1)
# 增加行合计
df.loc['合计'] = df.sum(axis=0)

数据平移

折叠代码块PYTHON 复制代码
1
data['经度_前1天'] = data.groupby('var')['经度'].shift(1)

宽窄表转换

折叠代码块PYTHON 复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
test = pd.DataFrame(fake_data, columns=['subject', 'A', 'B', 'C'])
test
subject A B C
0 math 88 70 60
1 english 90 80 78

# 转换为窄表
pd.melt(test, id_vars=['subject'])
data3 = pd.melt(data2, id_vars=['var1','var2'])
subject variable value
0 math A 88
1 english A 90
2 math B 70
3 english B 80
4 math C 60
5 english C 78

转二维表

折叠代码块PYTHON 复制代码
1
df.to_numpy()

字典转列表

折叠代码块PYTHON 复制代码
1
2
df.set_index('ID').T.to_dict('list')
{'p': [1, 3, 2], 'q': [4, 3, 2], 'r': [4, 0, 9]}

转字典列表

折叠代码块PYTHON 复制代码
1
2
3
datajs = data.to_json(orient='records',force_ascii=False)
# 名称,经度,维度,数值
[{"name":"虹桥火车站","lng":121.327908,"lat":31.20033,"value":3.5225437574},{"name":"上海火车站","lng":121.46396,"lat":31.255155,"value":7.0937954904}]

两列中的较大值

折叠代码块PYTHON 复制代码
1
df['z']=df[['x','y']].max(axis=1)