导入数据:
import pandas as pd
from sqlalchemy import create_engine
engin = create_engine('mysql+pymysql://root:123456@localhost:3306/test?charset=utf8')
data = pd.read_sql('meal_order_detail1', con=engin)
参数名称 | 说明 |
---|---|
objs | 接收多个Series,DataFrame,Panel的组合。表示参与链接的pandas对象的列表的组合。无默认 |
axis | 接收0或1。表示连接的轴向,默认为0 |
join | 接收inner或outer。表示其他轴向上的索引是按交集(inner)还是并集(outer)进行合并。默认为outer |
join_axes | 接收Index对象。表示用于其他n-1条轴的索引,不执行并集/交集运算 |
ignore_index | 接收boolean。表示是否不保留连接轴上的索引,产生一组新索引range(total_length)。默认为False |
keys | 接收sequence。表示与连接对象有关的值,用于形成连接轴向上的层次化索引。默认为None |
levels | 接收包含多个sequence的list。表示在指定keys参数后,指定用作层次化索引各级别上的索引。默认为None |
names | 接收list。表示在设置了keys和levels参数后,用于创建分层级别的名称。默认为None |
verify_integrity | 接收boolearn。表示是否检查结果对象新轴上的重复情况,如果发现则引发异常。默认为False |
a = data.iloc[:,:10]#所有行的前10列数据,按位置索引
b = data.iloc[:,10:]#所有行的10列后数据
pdcc = pd.concat([a,b], axis=1)#合并完成,axis=1表示横向,左右拼接
pdcc.shape
理解: data.iloc[:,:5]
[纵 : 横],纵向全选,横向选5个截至。
a = data.iloc[:100,:]
b = data.iloc[100:,:]
pd.concat([a,b]).shape#axis=0,默认可以不写
(2779, 19)
参数名称 | 说明 |
---|---|
other | 接收DataFrame或Series。表示要添加的新数据。无默认 |
ignore_index | 接收boolean。如果输入True,会对新生成的DataFrame使用新的索引(自动产生)而忽略原来数据的索引。默认为False |
verify_integrity | 接收boolean。如果输入True,那么当ignore_index为False时,会检查添加的数据索引是否冲突,如果冲突,则会添加失败。默认为False |
a.append(b).shape
(2779, 19)
(1) 导入数据
order = pd.read_csv('./meal_order_info.csv',encoding='gbk')
order.head()
order['info_id'] = order['info_id'].astype(str)
pd.merge(order, data, left_on='info_id', right_on='order_id')
参数名称 | 说明 |
---|---|
other | 接收DataFrame、Series或者包含了多个DataFrame的list。表示参与连接的其他DataFrame。无默认 |
on | 接收列名或者包含列名的list或tuple。表示用于连接的列名。默认为None |
how | 接收特定string。inner代表内连接;outer代表外连接;left和right分别代表左连接和右连接。默认为inner |
rsuffix | 接收string。表示用于追加到右侧重叠列名的末尾。无默认 |
lsuffix | 接收sring。表示用于追加到左侧重叠列名的末尾。无默认 |
sort | 根据连接键对合并后的数据进行排序,默认为True |
(1)更改order的主键名称
order.rename(columns={'info_id':'order_id'},inplace=True)
data.join(order, on='order_id', rsuffix='1')
参数名称 | 说明 |
---|---|
other | 接收DataFrame。表示参与重叠合并的另一个DataFrame。无默认 |
(1) 构造两个数组
import numpy as np
dis1 = {
'id':list(range(1,10)),
'cpu':['i7', 'i5', np.nan, 'i7', 'i7', 'i5', np.nan, np.nan,'i5']
}
a = pd.DataFrame(dis1)
dis2 = {
'id':list(range(1,10)),
'cpu':['i7', 'i5', 'i5', np.nan, 'i7', 'i5', 'i5', np.nan,'i5']
}
b = pd.DataFrame(dis2)
a.combine_first(b)
def delRep(list1):
list2=[]
for i in list1:
if i not in list2:
list2.append(i)
return list2
dish_set = set(dishes)
比较上述两种方法可以发现,方法一代码冗长。方法二代码简单了许多,但会导致数据的排列发生改变。
参数名称 | 说明 |
---|---|
subset | 接收string或sequence。表示进行去重的列。默认为None,表示全部列 |
keep | 接收特定string。表示重复时保留第几个数据。First:保留第一个。Last:保留最后一个。False:只要有重复都不保留。默认为first |
inplace | 接收boolean。表示是否在原表上进行操作。默认为False |
(1) 查看数据
data['dishes_name']
0 蒜蓉生蚝
1 蒙古烤羊腿
2 大蒜苋菜
3 芝麻烤紫菜
4 蒜香包
...
2774 白饭/大碗
2775 牛尾汤
2776 意文柠檬汁
2777 金玉良缘
2778 酸辣藕丁
Name: dishes_name, Length: 2779, dtype: object
(2) 数据单列去重
data['dishes_name'].drop_duplicates()
0 蒜蓉生蚝
1 蒙古烤羊腿
2 大蒜苋菜
3 芝麻烤紫菜
4 蒜香包
...
1024 海带结豆腐汤
1169 冰镇花螺
1411 冬瓜炒苦瓜
1659 超人气广式肠粉
2438 百里香奶油烤紅酒牛肉
Name: dishes_name, Length: 145, dtype: object
(3) 数据整体去重
data.drop_duplicates().shape
(2779, 19)
(4) 数据并列去重
data.drop_duplicates(subset=['order_id','emp_id']).shape
(278, 19)
data[['counts','amounts']].corr()
sim_dis = pd.DataFrame([],
index=['counts','amounts','dishes_name'],
columns=['counts','amounts','dishes_name'])
for i in ['counts','amounts','dishes_name']:
for j in ['counts','amounts','dishes_name']:
sim_dis.loc[i,j] = data[i].equals(data[j])
print (sim_dis)
counts amounts dishes_name
counts True False False
amounts False True False
dishes_name False False True
data.isnull()
dis1 = {
'id':list(range(1,10)),
'cpu':['i7', 'i5', np.nan, 'i7', 'i7', 'i5', np.nan, np.nan,'i5']
}
a = pd.DataFrame(dis1)
删除法分为删除观测记录和删除特征两种,它属于利用减少样本量来换取信息完整度的一种方法,是一种最简单的缺失值处理方法。
pandas中提供了简便的删除缺失值的方法dropna,该方法既可以删除观测记录,亦可以删除特征。
pandas.DataFrame.dropna(self, axis=0, how=‘any’, thresh=None, subset=None, inplace=False)
常用参数及其说明如下:
参数名称 | 说明 |
---|---|
axis | 接收0或1。表示轴向,0为删除观测记录(行),1为删除特征(列)。默认为0 |
how | 接收特定string。表示删除的形式。any表示只要有缺失值存在就执行删除操作。all表示当且仅当全部为缺失值时执行删除操作。默认为any |
subset | 接收类array数据。表示进行去重的列∕行。默认为None,表示所有列/行 |
inplace | 接收boolean。表示是否在原表上进行操作。默认为False |
#默认横向删除
a.dropna()
#删除指定列缺失数据
a.dropna(subset=['id'])
#删除缺失的列
a.dropna(axis=1)
注意: 这样删除缺失值并不会对原数据造成影响,需要变化的话可以加上inplace=True。
参数名称 | 说明 |
---|---|
value | 接收scalar,dict,Series或者DataFrame。表示用来替换缺失值的值。无默认 |
method | 接收特定string。backfill或bfill表示使用下一个非缺失值填补缺失值。pad或ffill表示使用上一个非缺失值填补缺失值。默认为None |
axis | 接收0或1。表示轴向。默认为1 |
inplace | 接收boolean。表示是否在原表上进行操作。默认为False |
limit | 接收int。表示填补缺失值个数上限,超过则不进行填补。默认为None |
(1) 指定替换为某值
a['cpu'].fillna('i7')
a['cpu'].fillna(a['cpu'].value_counts().index[0])
0 i7
1 i5
2 i7
3 i7
4 i7
5 i5
6 i7
7 i7
8 i5
Name: cpu, dtype: obje
(4) 利用均值替换
import numpy as np
dis1 = {
'id':list(range(1,10)),
'num':[7, 7, np.nan, 5, 4, 6, np.nan, np.nan,7]
}
a = pd.DataFrame(dis1)
a
a['num'].fillna(a['num'].mean())
0 7.0
1 7.0
2 6.0
3 5.0
4 4.0
5 6.0
6 6.0
7 6.0
8 7.0
Name: num, dtype: float64
(5) 插值法
删除法简单易行,但是会引起数据结构变动,样本减少;替换法使用难度较低,但是会影响数据的标准差,导致信息量变动。在面对数据缺失问题时,除了这两种方法之外,还有一种常用的方法—插值法.
常用的插值法有线性插值、多项式插值和样条插值等:
从拟合结果可以看出多项式插值和样条插值在两种情况下拟合都非常出色,线性插值法只在自变量和因变量为线性关系的情况下拟合才较为出色。
而在实际分析过程中,自变量与因变量的关系是线性的情况非常少见,所以在大多数情况下,多项式插值和样条插值是较为合适的选择。
SciPy库中的interpolate模块除了提供常规的插值法外,还提供了例如在图形学领域具有重要作用的重心坐标插值(BarycentricInterpolator)等。在实际应用中,需要根据不同的场景,选择合适的插值方法。
线性插值法:
x = np.array([1,2,3,6,7])
y = np.array([3,5,6,9,13])
from scipy.interpolate import interp1d
model = interp1d(x,y,kind='linear')
model([4,5])
结果:
array([7., 8.])
import matplotlib.pyplot as plt
plt.scatter(x,y)#蓝色的点
plt.plot(x, model(x),'r-')#插值后红色的线
plt.show()
拉格朗日插值法:
from scipy.interpolate import lagrange
f_lag = lagrange(x,y)
f_lag([4,5])
结果:
array([6.5, 7.2])
数据可视化:
import matplotlib.pyplot as plt
plt.scatter(x,y)#蓝色的点表示原数据
plt.plot(x, y,'c-')#浅绿色的线表示原数据
plt.scatter([4,5],model([4,5]),c='r')#红点表示线性插值点
plt.scatter([4,5],f_lag([4,5]),c='b')#红点表示拉格朗日插值点
#支持中文
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
plt.legend(['原点','原线','线性插值','拉格朗日插值'])
plt.show()
from scipy.interpolate import BSpline
y_bs = BSpline(x, y, k=1)
y_bs([4,5])
array([5.33333333, 5.66666667])
u = data['counts'].mean()
o = data['counts'].std()
index = data['counts'].apply(lambda x: x > u+3*o or x < u-3*o)#遍历查询(u-3*o,u+3*o)之外的数据,返回True和False
data.loc[index,'counts']#索引出异常值
94 5.0
176 3.0
238 4.0
270 4.0
346 4.0
...
2370 3.0
2458 3.0
2459 4.0
2461 6.0
2501 7.0
Name: counts, Length: 62, dtype: float64
(1)箱线图分析
import matplotlib.pyplot as plt
plt.boxplot(data['counts'])
plt.show()
(2)取出异常值
p = plt.boxplot(data['counts'])
p['fliers'][0].get_ydata()
array([ 2., 2., 2., 2., 5., 2., 2., 2., 2., 2., 3., 2., 2.,
2., 2., 4., 2., 4., 4., 4., 2., 4., 10., 4., 6., 2.,
6., 6., 8., 2., 2., 2., 6., 6., 4., 3., 4., 6., 2.,
6., 6., 2., 8., 3., 2., 2., 2., 4., 2., 2., 2., 2.,
3., 6., 8., 2., 2., 2., 2., 5., 2., 2., 5., 3., 4.,
2., 3., 2., 2., 4., 8., 2., 2., 3., 3., 2., 2., 2.,
4., 4., 2., 2., 2., 4., 6., 2., 3., 3., 3., 2., 2.,
2., 2., 2., 2., 3., 2., 3., 3., 2., 3., 2., 4., 6.,
2., 2., 2., 2., 2., 2., 2., 2., 2., 2., 4., 7., 2.,
2., 4., 8., 8., 4., 3., 3., 3., 2., 2., 2., 2., 2.,
2., 3., 4., 6., 7., 2., 2., 2., 2., 2., 2.])
导入数据:
import pandas as pd
data = pd.read_csv('./detail.csv', encoding='gbk')
data.head()
def MinMaxScale(data):
return (data - data.min()) / (data.max()-data.min())
a = MinMaxScale(data['counts'])
b = MinMaxScale(data['amounts'])
pd.concat([a,b],axis=1)
def StandScale(data):
return (data - data.mean()) / data.std()
a = StandScale(data['counts'])
b = StandScale(data['amounts'])
pd.concat([a,b],axis=1)
import numpy as np
def DecimalScale(data):
return data / 10**(np.ceil(data.abs().max()))
a = DecimalScale(data['counts'])
b = DecimalScale(data['amounts'])
pd.concat([a,b],axis=1)
参数名称 | 说明 |
---|---|
data | 接收array、DataFrame或者Series。表示需要哑变量处理的数据。无默认 |
prefix | 接收string、string的列表或者string的dict。表示哑变量化后列名的前缀。默认为None |
prefix_sep | 接收string。表示前缀的连接符。默认为‘_’ |
dummy_na | 接收boolean。表示是否为Nan值添加一列。默认为False |
columns | 接收类似list的数据。表示DataFrame中需要编码的列名。默认为None,表示对所有object和category类型进行编码 |
sparse | 接收boolean。表示虚拟列是否是稀疏的。默认为False |
drop_first | 接收boolean。表示是否通过从k个分类级别中删除第一级来获得k-1个分类级别。默认为False |
pd.get_dummies(data['dishes_name'])
参数名称 | 说明 |
---|---|
x | 接收数组或Series。代表需要进行离散化处理的数据。无默认 |
bins | 接收int,list,array,tuple。若为int,代表离散化后的类别数目;若为序列类型的数据,则表示进行切分的区间,每两个数间隔为一个区间。无默认 |
right | 接收boolean。代表右侧是否为闭区间。默认为True |
labels | 接收list,array。代表离散化后各个类别的名称。默认为空 |
retbins | 接收boolean。代表是否返回区间标签。默认为False |
precision | 接收int。显示的标签的精度。默认为3 |
pd.cut(data['amounts'],bins=5)
0 (36.4, 71.8]
1 (36.4, 71.8]
2 (0.823, 36.4]
3 (0.823, 36.4]
4 (0.823, 36.4]
...
10032 (0.823, 36.4]
10033 (0.823, 36.4]
10034 (36.4, 71.8]
10035 (0.823, 36.4]
10036 (0.823, 36.4]
Name: amounts, Length: 10037, dtype: category
Categories (5, interval[float64]): [(0.823, 36.4] < (36.4, 71.8] < (71.8, 107.2] < (107.2, 142.6] < (142.6, 178.0]]
统计频数:
pd.cut(data['amounts'],bins=5).value_counts()
(0.823, 36.4] 5461
(36.4, 71.8] 3157
(71.8, 107.2] 839
(142.6, 178.0] 426
(107.2, 142.6] 154
Name: amounts, dtype: int64
def samefreq(data, k):
w = data.quantile(np.arange(0,1 + 1/k, 1/k))
return pd.cut(data, w)
samefreq(data['amounts'], k=5).value_counts()
(18.0, 32.0] 2107
(39.0, 58.0] 2080
(32.0, 39.0] 1910
(1.0, 18.0] 1891
(58.0, 178.0] 1863
Name: amounts, dtype: int64