dige-python-pandas

3.数据分析处理库(Pandas)  --Page49
导入pandas
import pandas as pd

》1.数据读取
先把数据加载进来
df=pd.read_csv('./titanic.csv')
#展示读取数据,默认是前5条
df.head()


DataFrame结构
df.info()
结果:
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 418 entries, 0 to 417
Data columns (total 12 columns):
 #   Column       Non-Null Count  Dtype  
---  ------       --------------  -----  
 0   PassengerId  418 non-null    int64  
 1   Survived     418 non-null    int64  
 2   Pclass       418 non-null    int64  
 3   Name         418 non-null    object 
 4   Sex          418 non-null    object 
 5   Age          332 non-null    float64
 6   SibSp        418 non-null    int64  
 7   Parch        418 non-null    int64  
 8   Ticket       418 non-null    object 
 9   Fare         417 non-null    float64
 10  Cabin        91 non-null     object 
 11  Embarked     418 non-null    object 
dtypes: float64(2), int64(5), object(5)
memory usage: 39.3+ KB

#表示当前结果是DataFrame格式的,暂时将它视为一个二维矩阵
#行表示数据样本,列表示每个特征指标
df.info():打印当前读取的数据的部分信息,
如:数据样本规模,每列特征类型与个数,整体的内存占用等。


DataFrame属性
#返回索引
df.index
结果:
RangeIndex(start=0, stop=418, step=1)

#每一列特征的名字
df.columns
结果:
Index(['PassengerId', 'Survived', 'Pclass', 'Name', 'Sex', 'Age', 'SibSp',
       'Parch', 'Ticket', 'Fare', 'Cabin', 'Embarked'],
      dtype='object')

#每一列的类型,object表示python中的字符串
df.dtypes:
结果:
PassengerId      int64
Survived         int64
Pclass           int64
Name            object
Sex             object
Age            float64
SibSp            int64
Parch            int64
Ticket          object
Fare           float64
Cabin           object
Embarked        object
dtype: object

#取得数值矩阵
df.values
结果:
array([[892, 0, 3, ..., 7.8292, nan, 'Q'],
       [893, 1, 3, ..., 7.0, nan, 'S'],
       [894, 0, 2, ..., 9.6875, nan, 'Q'],
       ...,
       [1307, 0, 3, ..., 7.25, nan, 'S'],
       [1308, 0, 3, ..., 8.05, nan, 'S'],
       [1309, 0, 3, ..., 22.3583, nan, 'C']], dtype=object)










#数据索引
如果想取得某一列指标,以前可能会用到列索引,现在只需要指定名字即可。
age=df['Age']
age[:5]
结果:
0    34.5
1    47.0
2    62.0
3    27.0
4    22.0
Name: Age, dtype: float64

age[1:5]
结果:
1    47.0
2    62.0
3    27.0
4    22.0
Name: Age, dtype: float64

#DataFrame中可以直接选择数据的列名,读取数据时,read_csv会默认把读取数据中的第一行作为列名

如果要对其中数值进行操作,可将其结果单独取出
age.values[:5]
结果:
array([34.5, 47. , 62. , 27. , 22. ])
#pandas很多计算和处理的底层操作都是Numpy完成的

type(age)
结果:
pandas.core.series.Series

#read_csv完成后,最左侧会有一列数字,这相当于是给样本加了索引了。
#我们可以将姓名设置为索引,或者其他设置为索引
df=df.set_index("Name")
df.head()

#这样索引就变成了姓名
age=df['Age']
age['Kelly, Mr. James']
结果:
34.5


age[1:5]
结果:
Name
Wilkes, Mrs. James (Ellen Needs)                47.0
Myles, Mr. Thomas Francis                       62.0
Wirz, Mr. Albert                                27.0
Hirvonen, Mrs. Alexander (Helga E Lindqvist)    22.0
Name: Age, dtype: float64


age.values[1:5]
结果:
array([47., 62., 27., 22.])


age.values[1:5].dtype
结果:
dtype('float64')

df['Age']和df[['Age']]区别

#df['Age']的类型是Series
type(df['Age'])
pandas.core.series.Series

#df[['Age']]的类型是DataFrame
type(df[['Age']])
pandas.core.frame.DataFrame

#取多个列
df[['Age','Fare']][1:5]
结果:
Age Fare
Name
Wilkes, Mrs. James (Ellen Needs) 47.0 7.0000
Myles, Mr. Thomas Francis 62.0 9.6875
Wirz, Mr. Albert 27.0 8.6625
Hirvonen, Mrs. Alexander (Helga E Lindqvist) 22.0 12.2875


#Pandas的索引中有两个函数来查找数据
#iloc(): 用位置找数据
#找到第2个数据,索引从0开始
df.iloc[1]:
结果:
PassengerId       893
Survived            1
Pclass              3
Sex            female
Age              47.0
SibSp               1
Parch               0
Ticket         363272
Fare              7.0
Cabin             NaN
Embarked            S
Name: Wilkes, Mrs. James (Ellen Needs), dtype: object


#使用切片拿到一部分数据:
df.iloc[0:4]
结果:

PassengerId Survived Pclass Sex Age SibSp Parch Ticket Fare Cabin Embarked
Name
Kelly, Mr. James 892 0 3 male 34.5 0 0 330911 7.8292 NaN Q
Wilkes, Mrs. James (Ellen Needs) 893 1 3 female 47.0 1 0 363272 7.0000 NaN S
Myles, Mr. Thomas Francis 894 0 2 male 62.0 0 0 240276 9.6875 NaN Q
Wirz, Mr. Albert 895 0 3 male 27.0 0 0 315154 8.6625 NaN S


#找到指定样本数据的指定特征的数据
#找到前三条数据的第2、3、4列数据
df.iloc[0:4,1:4]

Survived Pclass Sex
Name
Kelly, Mr. James 0 3 male
Wilkes, Mrs. James (Ellen Needs) 1 3 female
Myles, Mr. Thomas Francis 0 2 male
Wirz, Mr. Albert 0 3 male



loc(): 用标签找数据
#直接通过名字找数据
df.loc['Kelly, Mr. James']
结果:
PassengerId       892
Survived            0
Pclass              3
Sex              male
Age              34.5
SibSp               0
Parch               0
Ticket         330911
Fare           7.8292
Cabin             NaN
Embarked            Q
Name: Kelly, Mr. James, dtype: object


#获得当前数据的某一列数据
df.loc['Kelly, Mr. James','Fare']
结果:
7.8292

#可以选择多个样本,":"表示取得全部特征
#名字之间的":"表示取两个名字之间的所有记录
df.loc['Kelly, Mr. James':'Myles, Mr. Thomas Francis',:]
结果:

PassengerId Survived Pclass Sex Age SibSp Parch Ticket Fare Cabin Embarked
Name
Kelly, Mr. James 892 0 3 male 34.5 0 0 330911 7.8292 NaN Q
Wilkes, Mrs. James (Ellen Needs) 893 1 3 female 47.0 1 0 363272 7.0000 NaN S
Myles, Mr. Thomas Francis 894 0 2 male 62.0 0 0 240276 9.6875 NaN Q


#对数据赋值
df.loc['Kelly, Mr. James','Fare']=1000


#Pandas中bool类型也可以作为索引
#选择船票价格大于40的旅客
df['Fare']>40
结果:
Name
Kelly, Mr. James                                False
Wilkes, Mrs. James (Ellen Needs)                False
Myles, Mr. Thomas Francis                       False
Wirz, Mr. Albert                                False
Hirvonen, Mrs. Alexander (Helga E Lindqvist)    False
                                                ...  
Spector, Mr. Woolf                              False
Oliva y Ocana, Dona. Fermina                     True
Saether, Mr. Simon Sivertsen                    False
Ware, Mr. Frederick                             False
Peter, Master. Michael J                        False
Name: Fare, Length: 418, dtype: bool


#通过bool类型来筛选船票价格大于40的乘客,并且展示前3条
df[df['Fare']>40][0:3]
结果:
PassengerId Survived Pclass Sex Age SibSp Parch Ticket Fare Cabin Embarked
Name
Snyder, Mrs. John Pillsbury (Nelle Stevenson) 904 1 1 female 23.0 1 0 21228 82.2667 B45 S
Chaffee, Mrs. Herbert Fuller (Carrie Constance Toogood) 906 1 1 female 47.0 1 0 W.E.P. 5734 61.1750 E31 S
Rothschild, Mr. Martin 912 0 1 male 55.0 1 0 PC 17603 59.4000 NaN C


#计算所有男性的平均年龄
df.loc[df['Sex']=='male','Age'].mean()
结果:
30.27273170731707

#就是大于70岁的乘客的人数
(df['Age']>70).sum()



#创建DataFrame
#简单的方法就是:创建一个字典,key表示特征名字,value表示各个样本的实际值,然后通过pd.DataFrame()函数创建
data={"country":['CN','US','IND'],"population":[14,3,12]}
df=pd.DataFrame(data)
df

结果:
country population
0 CN 14
1 US 3
2 IND 12


#pandas的设置
#获得展示的最大行数
pd.get_option("display.max_rows")
60

#
pd.set_option("display.max_rows",6)

#Series: 相当于是二维数据中的一行或一列
pd.Series(index=range(0,100))



#Series操作:
简单来说,读取的数据都是二维的,也就是DataFrame。
如果在数据中单独获取某列数据,那就是Series格式了,相当于是DataFrame是由Series组合得到的。

#创建Series
data=[10,11,12]
idx=['a','b','c']
sr=pd.Series(data=data,index=idx)
sr
结果:
a    10
b    11
c    12
dtype: int64


#索引操作(查询操作)
sr.loc['b']
结果:
11
sr.iloc[2]
12


#修改操作:
s1=sr.copy()
s1['a]=100
s1
结果:
a    100
b     11
c     12
dtype: int64



pandas统计分析
创建一个简单的Dataframe,既可以传入数据,也可以指定索引和列名
df=pd.DataFrame([[1,2,3],[4,5,6]],index=['a','b'],columns=['A','B','C'])
df
结果:
A B C
a 1 2 3
b 4 5 6

#相加,默认是对每列计算结果,相当于df.sum(axis=0)
df.sum()
结果:
A    5
B    7
C    9
dtype: int64


df.sum(axis=1)
结果:
a     6
b    15
dtype: int64


#同样其他函数类似
平均值: df.mean()
中位数: df.median()
最大值: df.max()
最小值: df.min()
更方便查看样本数据的特征: df.describe()

df.describe()
结果:

PassengerId Survived Pclass Age SibSp Parch Fare
count 418.000000 418.000000 418.000000 332.000000 418.000000 418.000000 417.000000
mean 1100.500000 0.363636 2.265550 30.272590 0.447368 0.392344 35.627188
std 120.810458 0.481622 0.841838 14.181209 0.896760 0.981429 55.907576
min 892.000000 0.000000 1.000000 0.170000 0.000000 0.000000 0.000000
25% 996.250000 0.000000 1.000000 21.000000 0.000000 0.000000 7.895800
50% 1100.500000 0.000000 3.000000 27.000000 0.000000 0.000000 14.454200
75% 1204.750000 1.000000 3.000000 39.000000 1.000000 0.000000 31.500000
max 1309.000000 1.000000 3.000000 76.000000 8.000000 9.000000 512.329200

以上展示了所有数值特征的统计结果,包含数据个数,均值,标准差,最大最小值等。

除了可以执行这些基本操作外,还可以统计二元属性,如:协方差、相关系数等,这些都是数据分析中重要指标

#协方差矩阵: 
df.cov()
结果:

PassengerId Survived Pclass Age SibSp Parch Fare
PassengerId 14595.166667 -1.352518 -2.720624 -59.369047 0.413669 5.107914 55.514238
Survived -1.352518 0.231960 -0.044037 -0.000088 0.043165 0.075213 5.159417
Pclass -2.720624 -0.044037 0.708690 -5.906358 0.000820 0.015467 -27.171232
Age -59.369047 -0.000088 -5.906358 201.106695 -1.135270 -0.704115 291.838610
SibSp 0.413669 0.043165 0.000820 -1.135270 0.804178 0.270100 8.607981
Parch 5.107914 0.075213 0.015467 -0.704115 0.270100 0.963203 12.635175
Fare 55.514238 5.159417 -27.171232 291.838610 8.607981 12.635175 3125.657074


#相关系数:
df.corr()
结果:

PassengerId Survived Pclass Age SibSp Parch Fare
PassengerId 1.000000 -0.023245 -0.026751 -0.034102 0.003818 0.043080 0.008211
Survived -0.023245 1.000000 -0.108615 -0.000013 0.099943 0.159120 0.191514
Pclass -0.026751 -0.108615 1.000000 -0.492143 0.001087 0.018721 -0.577147
Age -0.034102 -0.000013 -0.492143 1.000000 -0.091587 -0.061249 0.337932
SibSp 0.003818 0.099943 0.001087 -0.091587 1.000000 0.306895 0.171539
Parch 0.043080 0.159120 0.018721 -0.061249 0.306895 1.000000 0.230046
Fare 0.008211 0.191514 -0.577147 0.337932 0.171539 0.230046 1.000000


#统计某一列各个属性的比例情况,如:男性多少、女性多少,value_counts()起作用了

#统计该列所有属性个数
df['Sex'].value_counts()
结果:
male      266
female    152
Name: Sex, dtype: int64

#按照指定顺序,数字少的排在前面
df['Sex'].value_counts(ascending=True)
结果:
female    152
male      266
Name: Sex, dtype: int64

#年龄这种就不好处理了,因为年龄分布太分散了
df['Age'].value_counts(ascending=True)

60.50     1
0.83      1
34.50     1
0.92      1
36.50     1
         ..
18.00    13
30.00    15
22.00    16
24.00    17
21.00    17
Name: Age, Length: 79, dtype: int64


#可以将0-10岁属于少儿组,10-20属于青年组,这相当于将连续值进行离散化
#指定划分几个组
df['Age'].value_counts(ascending=True,bins=5)
(60.834, 76.0]       10
(0.0932, 15.336]     32
(45.668, 60.834]     42
(30.502, 45.668]     80
(15.336, 30.502]    168
Name: Age, dtype: int64



#pivot数据透视表
pivot用于展示数据透视表操作的,就是按照自己的方式来分析数据
example=pd.DataFrame({"Month":["Jan","Jan","Jan","Jan","Feb","Feb","Feb","Feb","March","March","March","March"],
"Category":["Transportation","Grocery","HouseHold","Entertainment","Transportation","Grocery","HouseHold","Entertainment","Transportation","Grocery","HouseHold","Entertainment"],"Amount":[74,235,175,100,115,240,225,125,90,260,200,120]})


Month Category Amount
0 Jan Transportation 74
1 Jan Grocery 235
2 Jan HouseHold 175
3 Jan Entertainment 100
4 Feb Transportation 115
5 Feb Grocery 240
6 Feb HouseHold 225
7 Feb Entertainment 125
8 March Transportation 90
9 March Grocery 260
10 March HouseHold 200
11 March Entertainment 120

#category:钱花在什么用途上了,Month:月份;Amount:金额
#统计每个月花费在各项用途上的金额

pivot1=example.pivot(index="Category",columns="Month" ,values="Amount")
pivot1
结果:

Month Feb Jan March
Category
Entertainment 125 100 120
Grocery 240 235 260
HouseHold 225 175 200
Transportation 115 74 90


#这几个月每项花费的总和:
#select month,category, sum(amount) as sum from detail_t group by month,category
pivot1.sum(axis=1)   #列级别的汇总
结果:
Category
Entertainment     345
Grocery           735
HouseHold         600
Transportation    279
dtype: int64

pivot1.sum(axis=0) #行级别的汇总
结果:
Month
Feb      705
Jan      584
March    670
dtype: int64


index,columns,values代表什么意思呢?看泰坦尼克号的例子:
df=pd.read_csv('titanic.csv')
df.pivot_table(index='Sex',columns='Pclass',values="Fare")
结果:

Pclass 1 2 3
Sex
female 115.591168 26.438750 13.735129
male 75.586551 20.184654 11.826350

PClass:代表船舱等级、Fare代表船票价格,
上述例子表示按乘客性别来分别统计各个舱位购票的平均价格

index:指定按什么属性来统计
columns:指定统计哪个指标
values:指定统计的实际指标值是什么
平均值是哪儿来的呢?平均值相当于是默认值,如果想指定最大/最小值,还需要额外参数。

#统计各个船舱的最大票价
df.pivot_table(index="Sex",columns="PClass",values="Fare" ,aggfunc="max")
结果:
Pclass 1 2 3
Sex
female 512.3292 65.0 69.55
male 262.3750 73.5 69.55

#统计各个船舱的人数
df.pivot_table(index="Sex" ,columns="Pclass" ,values="Fare", aggfunc="count")
结果:
Pclass 1 2 3
Sex
female 50 30 72
male 57 63 145

#首先按年龄将乘客分为:成年和未成年,再对两组乘客分别统计不同性别的平均获救可能性。
df['Underaged']=(df['Age']<=18)
df.pivot_table(index="Underaged",columns="Sex",values="Survived",aggfunc="mean")
结果:

Sex female male
Underaged
False 1 0
True 1 0


#groupby操作:
df=pd.DataFrame({"key":['a','b','c','a','b','c','a','b','c'],'data':[0,5,10,5,10,15,10,15,20]})
df
结果:
key data
0 a 0
1 b 5
2 c 10
3 a 5
4 b 10
5 c 15
6 a 10
7 b 15
8 c 20

#统计各个key对应的data的总和是多少
#select key,sum(data) from table group by key 
df.groupby("key").sum()
结果:
data
key
a 15
b 30
c 45


#换成均值,如何计算?
import numpy as np
df.groupby("key").aggregate(np.mean)
结果:
data
key
a 5
b 10
c 15

#按照性别统计年龄的平均值
df=pd.read_csv("./titanic.csv")
df.groupby("Sex")['Age'].mean()
结果:
Sex
female    30.272362
male      30.272732
Name: Age, dtype: float64


#groupby还有很多参数可以设置
df=pd.DataFrame({"A":['foo','bar','foo','bar','foo','bar','foo','foo'],
"B":['one','one','two','three','two','two','one','three'],
"C":np.random.randn(8),
"D":np.random.randn(8)
})

结果:
A B C D
0 foo one 0.190386 -1.805475
1 bar one -1.546554 0.991953
2 foo two 1.927603 1.094341
3 bar three -0.826420 0.433135
4 foo two 0.503680 1.409153
5 bar two 0.116226 -1.577756
6 foo one 0.225430 -0.036675
7 foo three -0.852578 0.964783

#观察groupby某一列后结果的数量,可以调用count()属性
#表示A在取不同值时,BCD中样本的数量
#结果中3和5对应了原始数据中样本的个数
grped=df.groupby("A")
grped.count()
结果:
B C D
A
bar 3 3 3
foo 5 5 5

#指定多个进行groupby
grped=df.groupby(["A",'B'])
grped.count()

结果:
C D
A B
bar one 1 1
three 1 1
two 1 1
foo one 2 2
three 1 1
two 2 2


#指定好操作方法之后,还需要指定一下计算或统计的方法,比如求和:
grped=df.groupby(["A",'B'])
grped.aggregate(np.sum)
结果:
C D
A B
bar one -1.546554 0.991953
three -0.826420 0.433135
two 0.116226 -1.577756
foo one 0.415816 -1.842150
three -0.852578 0.964783
two 2.431283 2.503495

#此处索引就是按传入参数的顺序来指定的,如果习惯数值索引的话,可以as_index=false
grped=df.groupby(["A",'B'],as_index=False)
grped.aggregate(np.sum)
结果:
A B C D
0 bar one -1.546554 0.991953
1 bar three -0.826420 0.433135
2 bar two 0.116226 -1.577756
3 foo one 0.415816 -1.842150
4 foo three -0.852578 0.964783
5 foo two 2.431283 2.503495

#groupby之后,仍然可以使用describe()方法来展示所有统计信息

grped.describe()
结果:
C D
count mean std min 25% 50% 75% max count mean std min 25% 50% 75% max
0 1.0 -1.546554 NaN -1.546554 -1.546554 -1.546554 -1.546554 -1.546554 1.0 0.991953 NaN 0.991953 0.991953 0.991953 0.991953 0.991953
1 1.0 -0.826420 NaN -0.826420 -0.826420 -0.826420 -0.826420 -0.826420 1.0 0.433135 NaN 0.433135 0.433135 0.433135 0.433135 0.433135
2 1.0 0.116226 NaN 0.116226 0.116226 0.116226 0.116226 0.116226 1.0 -1.577756 NaN -1.577756 -1.577756 -1.577756 -1.577756 -1.577756
3 2.0 0.207908 0.024780 0.190386 0.199147 0.207908 0.216669 0.225430 2.0 -0.921075 1.250730 -1.805475 -1.363275 -0.921075 -0.478875 -0.036675
4 1.0 -0.852578 NaN -0.852578 -0.852578 -0.852578 -0.852578 -0.852578 1.0 0.964783 NaN 0.964783 0.964783 0.964783 0.964783 0.964783
5 2.0 1.215642 1.006866 0.503680 0.859661 1.215642 1.571622 1.927603 2.0 1.251747 0.222606 1.094341 1.173044 1.251747 1.330450 1.409153

#设置自己所需要的统计目标
grped=df.groupby("A")
结果:
sum mean std
A
bar -2.256748 -0.752249 0.833867
foo 1.994521 0.398904 0.998459




#常用函数操作:
#merge函数
#数据处理可能需要对提取的特征进行整合,
#我们要做的就是把所有特征汇总在一起,
left=pd.DataFrame({"key":['K0','K1','K2','K3'],
   "A":['A0','A1','A2','A3'],
   "B":['B0','B1','B2','B3']
})
right=pd.DataFrame({"key":['K0','K1','K2','K3'],
   "C":['C0','C1','C2','C3'],
   "D":['D0','D1','D2','D3']
})

left: 
key A B
0 K0 A0 B0
1 K1 A1 B1
2 K2 A2 B2
3 K3 A3 B3

right: 
key C D
0 K0 C0 D0
1 K1 C1 D1
2 K2 C2 D2
3 K3 C3 D3

res=pd.merge(left,right,on='key')
结果:

key A B C D
0 K0 A0 B0 C0 D0
1 K1 A1 B1 C1 D1
2 K2 A2 B2 C2 D2
3 K3 A3 B3 C3 D3


left1=pd.DataFrame({"key1":['K0','K1','K2','K3'],
"key2":['K0','K1','K2','K3'],
   "A":['A0','A1','A2','A3'],
   "B":['B0','B1','B2','B3']
})
right1=pd.DataFrame({"key1":['K0','K1','K2','K3'],
"key2":['K0','K1','K2','K4'],
   "C":['C0','C1','C2','C3'],
   "D":['D0','D1','D2','D3']
})

left1:

key1 key2 A B
0 K0 K0 A0 B0
1 K1 K1 A1 B1
2 K2 K2 A2 B2
3 K3 K3 A3 B3

right1:
key1 key2 C D
0 K0 K0 C0 D0
1 K1 K1 C1 D1
2 K2 K2 C2 D2
3 K3 K4 C3 D3

res1=pd.merge(left1,right1,on=['key1','key2'])
res1
结果:
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K1 A1 B1 C1 D1
2 K2 K2 A2 B2 C2 D2

#前三行相同的都组合在一起了,第4行被抛弃了,如果需要所有的结果,需要加一个how参数
res1=pd.merge(left1,right1,on=['key1','key2'],how='outer')
res1
结果:

key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K1 A1 B1 C1 D1
2 K2 K2 A2 B2 C2 D2
3 K3 K3 A3 B3 NaN NaN
4 K3 K4 NaN NaN C3 D3

#还可以加入详细的组合说明,指定indicator=True即可.
res1=pd.merge(left1,right1,on=['key1','key2'],how='outer',indicator=True)
res1
结果:
key1 key2 A B C D _merge
0 K0 K0 A0 B0 C0 D0 both
1 K1 K1 A1 B1 C1 D1 both
2 K2 K2 A2 B2 C2 D2 both
3 K3 K3 A3 B3 NaN NaN left_only
4 K3 K4 NaN NaN C3 D3 right_only

#也可以设置只考虑左边或右边的数据:
res=pd.merge(left1,right1,how='left')
res
结果:
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K1 A1 B1 C1 D1
2 K2 K2 A2 B2 C2 D2
3 K3 K3 A3 B3 NaN NaN

res=pd.merge(left1,right1,how='right')
res
结果:
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K1 A1 B1 C1 D1
2 K2 K2 A2 B2 C2 D2
3 K3 K4 NaN NaN C3 D3


#排序操作:
dat=pd.DataFrame({"group":['a','a','a','b','b','b','c','c','c'],
   'data':[4,3,2,1,12,3,4,5,7]
})
dat

结果:
group data
0 a 4
1 a 3
2 a 2
3 b 1
4 b 12
5 b 3
6 c 4
7 c 5
8 c 7

#排序时,可指定升序或降序,还可指定按照多个指标排序
dat.sort_values(by=['group','data'],ascending=[False,True],inplace=True)
dat
结果:
group data
6 c 4
7 c 5
8 c 7
3 b 1
5 b 3
4 b 12
2 a 2
1 a 3
0 a 4

#by参数用于设置要排序的列,ascending用于设置升降序,False为降序,True为升序



#缺失值处理
#数据可能不干净或者有缺失值或重复片段
dat=pd.DataFrame({"k1":['one']*3+['two']*4,
  "k2":[3,2,1,3,3,4,4]
})
dat
结果:
k1 k2
0 one 3
1 one 2
2 one 1
3 two 3
4 two 3
5 two 4
6 two 4

#去掉重复的多余数据
dat.drop_duplicates()
结果:

k1 k2
0 one 3
1 one 2
2 one 1
3 two 3
5 two 4

#只考虑某一列的重复情况,其他都丢弃
dat.drop_duplicates(subset='k1')
结果:
k1 k2
0 one 3
3 two 3

#往数据中增加新列,可以直接指定新列名或使用assign函数
df=pd.DataFrame({"d1":np.random.randn(5),'d2':np.random.randn(5)})
df2=df.assign(ration=df['d1']/df['d2'])
df2
结果:

d1 d2 ration
0 0.144536 -0.932273 -0.155037
1 0.966555 1.032114 0.936481
2 -1.308448 -0.457537 2.859767
3 -1.215160 -2.182149 0.556864
4 -0.403131 -0.366450 1.100099


#缺失值情况,pandas一般使用NaN来表示
df=pd.DataFrame([range(3),[0,np.nan,0],[0,0,np.nan],range(3)])
df
结果:
0 1 2
0 0 1.0 2.0
1 0 NaN 0.0
2 0 0.0 NaN
3 0 1.0 2.0

#创建时加入两个缺失值,可通过isnull()来判断所有缺失情况
df.isnull()
结果:
0 1 2
0 False False False
1 False True False
2 False False True
3 False False False


#输出结果代表数据缺失情况,True代表数据缺失,我们更想知道某列是否存在缺失值
df.isnull().any()
结果:
0    False
1     True
2     True
dtype: bool


#any()相当于只要有一个缺失就意味着存在缺失情况,也可以自己指定检查的维度
df.isnull().any(axis=1)
结果:
0    False
1     True
2     True
3    False
dtype: bool


#遇到缺失值可以选择填充方法改善
df.fillna(5)
结果
0 1 2
0 0 1.0 2.0
1 0 5.0 0.0
2 0 0.0 5.0
3 0 1.0 2.0


#apply自定义函数
dat=pd.DataFrame({"food":['a1','a2','b1','b2','b3','c1','c2'],
  "data":[1,2,3,4,5,6,7]
})

结果:
food data
0 a1 1
1 a2 2
2 b1 3
3 b2 4
4 b3 5
5 c1 6
6 c2 7

def food_map(series):
pre=series['food'][:1]
if pre=='a':
return 'A'
elif pre=='b':
return 'B'
elif pre=='c':
return 'C'
dat['food_map']=dat.apply(food_map,axis='columns')
结果:
food data food_map
0 a1 1 A
1 a2 2 A
2 b1 3 B
3 b2 4 B
4 b3 5 B
5 c1 6 C
6 c2 7 C


#首先定义一个映射函数,若想改变food列的所有值,只需要调用apply函数即可。




#时间操作:
当拿到时间特征时,最好将其转换为标准格式
#创建一个时间戳
ts=pd.Timestamp('2023-07-20')
结果
Timestamp('2023-07-20 00:00:00')

print(ts.year)
print(ts.month)
print(ts.day)
结果:
2023
7
20

ts+pd.Timedelta('5 days')
结果:
Timestamp('2023-07-25 00:00:00')

#时间特征只要满足标准格式就可以调用各种函数和属性了
s=pd.Series(['2023-07-01 01:00:00','2023-07-04 13:00:00','2023-07-08 23:00:00'])
s
结果:
0    2023-07-01 01:00:00
1    2023-07-04 13:00:00
2    2023-07-08 23:00:00
dtype: object

ts1=pd.to_datetime(s)
ts1
结果:
0   2023-07-01 01:00:00
1   2023-07-04 13:00:00
2   2023-07-08 23:00:00
dtype: datetime64[ns]


#转换成标准格式后,注意到dtype类型变成了datetime64,就可以调用各种属性就行统计分析了。
ts1.dt.hour
结果:
0     1
1    13
2    23
dtype: int64

#星期几,从星期一开始,星期一是0
ts1.dt.weekday
结果:
0    5
1    1
2    5
dtype: int64


#如果没有给具体时间特征,可以自己创建
pd.Series(pd.date_range(start='2023-07-01',periods=10,freq='12H'))
结果:
0   2023-07-01 00:00:00
1   2023-07-01 12:00:00
2   2023-07-02 00:00:00
3   2023-07-02 12:00:00
4   2023-07-03 00:00:00
5   2023-07-03 12:00:00
6   2023-07-04 00:00:00
7   2023-07-04 12:00:00
8   2023-07-05 00:00:00
9   2023-07-05 12:00:00
dtype: datetime64[ns]


#读取数据时,如果想以时间特征为索引,可以将parse_dates参数设置为True
data=pd.read_csv('./titanic.csv',index_col=0,parse_dates=True)


#resample重采样
data.resample('D').mean().head(): 
#原始数据中每天都有好几条数据,如果想统计的是每天都平均指标,或者计算最大值,最小值,只需要把mean()更换为max()/min()即可。

#如果想按3天为一个周期进行统计
data.resample('3D').mean().head()

#按月统计也类似
data.resample('M').mean().head()



#绘图操作:
可以使用专门的工具包,如:matplotlib , seaborn
#pandas中基本绘图方法:

#notebook中使用绘图操作先执行此命令
%matplotlib inline
df=pd.DataFrame(np.random.randn(10,4).cumsum(0),index=np.arange(0,100,10))
columns=['A','B','C','D']
df.plot()



#
import matplotlib.pyplot as plt
#指定子图2行1列的形式
fig,axes=plt.subplots(2,1)
data=pd.Series(np.random.randn(16),index=list('abcdefghijklmnop'))
#axes[0]表示第一个子图
data.plot(ax=axes[0],kind='bar')
#aexs[1]表示第二个子图,在第一个子图下方
data.plot(ax=axes[1],kind='barh')


#还可以指定绘图的种类,例如条形图,散点图
df=pd.DataFrame(np.random.rand(6,4),index=['one','two','three','four','five','six'],columns=pd.Index(['A','B','C','D'],name='Genus'))
结果:

Genus A B C D
one 0.511267 0.516317 0.144777 0.122106
two 0.899395 0.844618 0.588580 0.680569
three 0.427250 0.371885 0.211861 0.724365
four 0.072342 0.419507 0.045960 0.651088
five 0.466297 0.783871 0.665737 0.018478
six 0.012802 0.577761 0.066325 0.207712

df.plot(kind='bar')



#大数据处理技巧
#数值类型转换:
#下面一个稍大的数据集,特征有些多,有161列,目标尽可能的减少占用的内存
g1=pd.read_csv('game.csv')
g1.head
#5行×161列

#共171907个数据样本
g1.shape
#(171907,161)

#指定成deep表示要详细展示当前数据占用的内存
g1.info(memory_usage='deep')
memory usage: 860.5MB
输出结果显示读取这份数据占用860.5M内存,数据类型主要有3种,其中float64类型有77个,int64有6个特征,object类型有78个特征