1. 程式人生 > 實用技巧 >萬字長文,Python資料分析實戰,使用Pandas進行資料分析

萬字長文,Python資料分析實戰,使用Pandas進行資料分析

文章目錄

很多人學習python,不知道從何學起。
很多人學習python,掌握了基本語法過後,不知道在哪裡尋找案例上手。
很多已經做案例的人,卻不知道如何去學習更加高深的知識。
那麼針對這三類人,我給大家提供一個好的學習平臺,免費領取視訊教程,電子書籍,以及課程的原始碼!
QQ群:101677771

一、Pandas的使用

1.Pandas介紹

Pandas的主要應用包括:

  • 資料讀取
  • 資料整合
  • 透視表
  • 資料聚合與分組運算
  • 分段統計
  • 資料視覺化

Pandas的使用很靈活,最重要的兩個資料型別是DataFrameSeries

對DataFrame最直觀的理解是把它當成一個Excel表格檔案,如下:

索引是從0開始的,也可以將某一行設定為index索引;
missing value為缺失值。

DataFrame的一列就是Series,Series可以轉化為dataframe,呼叫方法函式to_frame()

即可。

2.Pandas基本操作

Series的操作

Series的常見操作如下:

sis = Series([4,7,-5,3]
sis.to_frame()
sis.value_counts() # 統計每個唯一值的所有出現次數
sis.size
sis.shape
sis.count() # 返回非缺失值的數目
sis.min()
sis.max()
sis.median()
sis.std()
sis.sum()
sis.describe() # 返回摘要統計資訊和幾個分位數
sis.isnull() # 非空值
sis.fillna(0) # 用0來補充缺失值
#上述函式可以結合使用,如下
sis.isnull().sum()# 統計空值的個數

建立DataFrame

建立資料幀的語法如下:

pd.DataFrame( data=None, index=None, columns=None, dtype=None, copy=False)

引數說明:

  • data:可選資料型別,如:ndarray,series,map,lists,dict,constant和另一個DataFrame
  • index:行標籤索引,預設值np.arrange(n),不計入df列
  • columns:列標籤索引,預設值np.arrange(n),不計入df行
  • dtype:每列的資料型別
  • copy:預設值False,引用/複製資料

常見的幾種建立資料幀的方式如下:

pd.set_option("max_columns",10,"max_rows",20) # 設定最大列數和最大行數
df = pd.DataFrame()  # 空資料幀
df = pd.DataFrame(['a','b','c','d'])  # 從一維列表建立
df = pd.DataFrame([['Alex',10],['Bob',12],['Clarke',13]], dtype=float)  # 從二維列表建立,浮點型數字
df = pd.DataFrame({'Name':['Tom', 'Jack', 'Steve', 'Ricky'],'Age':[28,34,29,42]})  # 從字典建立,字典鍵預設為列標籤

常見列操作

列名參與代數運算,表示列中每一個元素都與該數字進行同樣的操作,如下:

movie = pd.read_csv('movie.csv')
imdb_score = movie['imdb_score']
imdb_score + 1 # 每一個列值加1
imdb_score * 2.5 # 給每一個列值乘2.5
imdb_score > 7 # 判斷每一個列值是否大於7
imdb_score=="hello" # 判斷是否等於字串
imdb_score.floordiv(7)     # imdb_score // 7,整數除法
imdb_score.gt(7)        # imdb_score > 7
imdb_score.eq('James Cameron')  # imdb_score == 'James Cameron'
type(imdb_score)
imdb_score.astype(int).mod(5) #每一個列值取模

sex_age = wl_melt['sex_age'].str.split(expand=True) # 對列使用字串的多個方法

建立、刪除列,通過[列名]來完成,如下:

movie["new_col"]=0
movie.insert(0, 'id', np.arange(len(movie))) # 插入新的列
movie["new_col"].all() #用來檢測所有的布林值都為True,用於比較兩列是否相等

設定索引相關操作:

movie2 = movie.set_index('movie_title') # set_index()給行索引命名
movie2.reset_index() #復原索引
movie.rename(index=,columns=) # 其中引數值為鍵值對,鍵為舊值,值為新值。
movie.columns.tolist()
movie.columns=new_columns

# 索引第1個行索引的值
idx = pd.Index(list('abc'))
idx.get_level_values(0)

特殊的列選擇如下:

movie.get_dtype_counts() # 輸出每種特定資料型別的列數
movie.select_dtypes(include=['int']).head() # 僅選擇整數列
movie.filter(like='facebook').head() # like引數表示包含此字串
movie.filter(regex='\d').head() # movie.filter支援正則表示式
movie.filter(items=['actor_1_name', 'asdf']) # 傳入精確列名的列表

常見行操作

新增新行,用loc指定:

new_data_list = ['Aria', 1]
names.loc[4] = new_data_list
#等價於
names.loc[4] = ['Aria', 1]
names.append({'Name':'Aria', 'Age':1}, ignore_index=True) # append方法可以同時新增多行,此時要放在列表中
data_dict = bball_16.iloc[0].to_dict()
# keys引數可以給兩個DataFrame命名,names引數可以重新命名每個索引層
pd.concat(s_list, keys=['2016', '2017'], names=['Year', 'Symbol'])
pres_41_45['President'].value_counts()

DateFrame的基本操作

選取多個列時,引數用中括號[]括起來:

movie[['actor_1_name', 'actor_2_name',]] # 裡面那個[]不要少

方法鏈:
點記號.表示函式呼叫順序的方式,要求為返回值必須為另外一個物件,如下:

person.drive('store').buy('food').drive('home').prepare('food').cook('food').serve('food').eat('food').cleanup('dishes')

DataFrame中操作如下:

actor_1_fb_likes.fillna(0).astype(int).head()

對整個資料幀的操作:

movie.shape
movie.count()
movie.min() # 各列的最小值
movie.isnull().any().any() # 判斷整個DataFrame有沒有缺失值,方法是連著使用兩個any

movie.isnull().sum() # 統計缺失值最主要方法是使用isnull方法
movie.sort_values('UGDS_HISP', ascending=False)# 按照某一列排序
movie.dropna(how='all')# 如果所有列都是缺失值,則將其去除

時間操作

pd.to_datetime能夠將整個列表或一系列字串或整數轉換為時間戳

使用如下:

s = pd.Series(['12-5-2015', '14-1-2013', '20/12/2017', '40/23/2017'])
pd.to_datetime(s, dayfirst=True, errors='coerce')

時間戳操作如下:

pd.Timestamp(year=2012, month=12, day=21, hour=5,minute=10, second=8, microsecond=99)
pd.Timestamp('2016/1/10')
pd.Timestamp('2016-01-05T05:34:43.123456789')
pd.Timestamp(500) # 可以傳遞整數,表示距離1970-01-01 00:00:00.000000000的毫秒數
pd.to_datetime('2015-5-13') # 類似函式有pd.to_dataframe

to_timedelta()方法可以產生一個Timedelta物件,還可以和Timestamp互相加減,甚至可以相除返回一個浮點數,如下:

# to_timedelta產生Timedelta物件。
pd.Timedelta('12 days 5 hours 3 minutes 123456789 nanoseconds')
time_strings = ['2 days 24 minutes 89.67 seconds', '00:45:23.6']
pd.to_timedelta(time_strings)
# Timedeltas和Timestamps互相加減
pd.Timedelta('12 days 5 hours 3 minutes') * 2
ts = pd.Timestamp('2016-10-1 4:23:23.9')
ts.ceil('h') # Timestamp('2016-10-01 05:00:00')
td.total_seconds()

可以在匯入的時候將時間列設為index,然後可以加快速度,時間支援部分匹配

# REPORTED_DATE設為了行索引,所以就可以進行智慧Timestamp物件切分。
crime = crime.set_index('REPORTED_DATE')# .sort_index()
crime.loc['2016-05-12 16:45:00']
# 選取2012-06的資料
crime.loc[:'2012-06']
crime.loc['2016-05-12']

# 也可以選取一整月、一整年或某天的某小時
crime.loc['2016-05'].shape
crime.loc['2016'].shape
crime.loc['2016-05-12 03'].shape
crime.loc['Dec 2015'].sort_index()

# 用at_time方法選取特定時間
crime.at_time('5:47').head()
crime.plot(figsize=(16,4), title='All Denver Crimes')
crime_sort.resample('QS-MAR')['IS_CRIME', 'IS_TRAFFIC'].sum().head()

Pandas中關於時間的概念和比較如下:

時間型別標量類陣列類pandas資料型別基本建立方法
Date times Timestamp DatetimeIndex datetime64[ns] or datetime64[ns, tz] to_datetime or date_range
Time deltas Timedelta TimedeltaIndex timedelta64[ns] to_timedelta or timedelta_range
Time spans Period PeriodIndex period[freq] Period or period_range
Date offsets DateOffset None None DateOffset

3.Pandas進行資料分析

讀取資料

college = pd.read_csv('college.csv')
employee = pd.read_csv('employee.csv')
college.head()
college.shape
display(college.describe(include=[np.number]).T) # 統計數值列,並進行轉置

選擇資料子集

直接在序列或資料幀之後加[]即可選擇指定的資料集。

.iloc索引器只按整數位置進行選擇,其工作方式與Python列表類似,區間為前閉後開;
.loc索引器只按索引標籤進行選擇,這與Python字典的工作方式類似,區間為後閉後開。
它們對行列均可以選擇。

使用如下:

college.iloc[:, [4,6]].head( ) # 選取兩列的所有的行
college.loc[:, ['WOMENONLY', 'SATVRMID']]
college.iloc[[60, 99, 3]].index.tolist() # .index.tolist()可以直接提取索引標籤,生成一個列表
college.iloc[5, -4] # 整數索引
college.loc['The University of Alabama', 'PCTFLOAN'] # 標籤索引
college[10:20:2] # 逐行讀取

# Series也可以進行同樣的切片
city = college['CITY']
city[10:20:2]

資料清洗

stack方法可以將每一行所有的列值轉換為行值,unstack方法可以將其還原,如下:

state_fruit = pd.read_csv('state_fruit.csv', index_col=0)
state_fruit.stack() # 再使用reset_index()將結果轉換為dataframe;給.columns賦值可以重新命名列
# 也可以使用rename_axis給不同的行索引層級命名
state_fruit.stack().rename_axis(['state', 'fruit']).reset_index(name='weight')

read_csv()方法只選取特定的列,指定uscols引數,如下:

usecol_func = lambda x: 'UGDS_' in x or x == 'INSTNM'
college = pd.read_csv('data/college.csv',usecols=usecol_func)

透視表pivot_table是一個很重要的概念,透視針對的物件是不同的列名,用法如下:

pandas.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All', observed=False)[source]

其中引數:
index引數接受一個(或多個)不進行透視的列,其唯一值將放在索引中;
columns引數接受一個或多個列,該列將被透視,其唯一值將被生成列名;
values引數接受一個或多個要聚合的列;
aggfunc引數確定如何聚合values引數中的列。

具體可參考https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.pivot_table.html

拼接方法包括:
concat()提供了基於軸的連線靈活性(所有行或所有列);
append()是特殊情況的concat()( case(axis=0, join=‘outer’));
join()是基於索引(由set_index設定)的,其變數為['left', 'right', 'inner', 'couter']
merge()是基於兩個資料幀中的每一個特定列,這些列是像’left_on’、‘right_on’、'on’一樣的變數。

布林索引

布林索引也叫布林選擇,通過提供布林值值來選擇行,這些布林值通常儲存在一個序列中,不同條件可以進行與或非(&、|、~)操作,但是在Python中,位運算子的優先順序高於比較運算子,所以需要加括號。
如下:

criteria1 = movie.imdb_score > 8
criteria2 = movie.content_rating == 'PG-13'
criteria3 = (movie.title_year < 2000) | (movie.title_year >= 2010) # 括號不能少
final=criteria1 & criteria2 & criteria3
college[final] # 作為索引,直接選擇值為True的行
employee.BASE_SALARY.between(80000, 120000) # 用between來選擇
criteria = ~employee.DEPARTMENT.isin(top_5_depts) # 排除最常出現的5家單位
employee[criteria].head()

條件複雜時,可以採用資料幀的query方法,如下:

df.query('A > B') # 等價於df[df.A > df.B]
 # 確定選取的部門和列
depts = ['Houston Police Department-HPD', 'Houston Fire Department (HFD)']
select_columns = ['UNIQUE_ID', 'DEPARTMENT', 'GENDER', 'BASE_SALARY']
qs = "DEPARTMENT in @depts and GENDER == 'Female' and 80000 <= BASE_SALARY <= 120000"
emp_filtered = employee.query(qs)
emp_filtered[select_columns].head()

對DataFrame的行呼叫msak()方法,使得所有滿足條件的資料都消失:

criteria = criteria1 | criteria2
movie.mask(criteria).head()

對不滿足條件的值進行替換,使用pandas的where語句。
如下:

s = pd.Series(range(5))
s.where(s > 1, 10)

group_by()的使用

通用資料分析模式:
將資料分解為獨立的可管理塊,獨立地將函式應用於這些塊,然後將結果組合在一起,
如下:

這需要使用到pandas提供的groupby()方法,可以對資料進行分組並呼叫聚合函式操作。

Pandas中,cut()方法用來把一組資料分割成離散的區間;
groupby()用於分組,並且可以對分組進行迭代,還可以使用分組運算方法即聚合函式agg():針對某列使用agg()時進行不同的統計運算聚合size方法,同時聚合多種方法。

假設有資料:

import pandas as pd

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)})
df

即:

分組迭代:

grouped = df.groupby('A')
for name, group in grouped:
      print(name)
      print(group)

列印:

bar
     A      B         C         D
1  bar    one  0.991265  0.005204
3  bar  three -0.791591 -0.576221
5  bar    two -1.587038  0.634791
foo
     A      B         C         D
0  foo    one -1.987942 -0.092403
2  foo    two  0.786344 -0.575798
4  foo    two  0.487330 -0.695639
6  foo    one  0.937217 -1.001144
7  foo  three -0.750302  1.495382

獲取分組:

#獲得一個分組get_group
grouped.get_group('bar')

顯示:

使用聚合函式:

grouped = df.groupby('A')
grouped['C'].agg([np.sum, np.mean, np.std])

顯示:

聚合函式統計個數:

df = pd.DataFrame({'Year' : ['2001', '2002', '2001', '2002',
                          '2001', '2002', '2001', '2002'],
                   'score' : ['primary', 'second', 'third', 'fourth',
                          'primary', 'second', 'fourth', 'third'],
                   'C' : [1,2,1,2,1,2,1,2],
                   'D' : np.random.randn(8)})

grouped = df.groupby('Year')
print (grouped['C'].agg(np.size))

列印:

Year
2001    4
2002    4
Name: C, dtype: int64

聚合函式中使用多種函式:

grouped = df.groupby('Year')
print (grouped['C'].agg([np.size,np.sum,np.mean]))

列印:

size  sum  mean
Year                 
2001     4    4     1
2002     4    8     2

更進一步操作:

score = lambda x: (x - x.mean())
print(df)
print('----------')
print(grouped['C'].agg(np.mean))
print('----------')
print (grouped['C'].transform(score))

列印:

   Year    score  C         D
0  2001  primary  1 -0.135237
1  2002   second  2  0.346450
2  2001    third  1 -0.004958
3  2002   fourth  2  2.722841
4  2001  primary  1  0.209729
5  2002   second  2  0.308275
6  2001   fourth  1  0.825608
7  2002    third  2 -0.569078
----------
Year
2001    1
2002    2
Name: C, dtype: int64
----------
0    0
1    0
2    0
3    0
4    0
5    0
6    0
7    0
Name: C, dtype: int64

進一步舉例說明如下:

# 按照AIRLINE分組,使用agg方法,傳入要聚合的列和聚合函式
flights.groupby('AIRLINE').agg({'ARR_DELAY':'mean'}).head()

# 或者要選取的列使用索引,聚合函式作為字串傳入agg
flights.groupby('AIRLINE')['ARR_DELAY'].agg('mean').head()
flights.groupby('AIRLINE')['ARR_DELAY'].mean().head()

#分組可以是多組,選取可以是多組,聚合函式也可以是多個,此時一一對應
flights.groupby(['AIRLINE', 'WEEKDAY'])['CANCELLED', 'DIVERTED'].agg(['sum',
'mean']).head(7)

#可以對同一列施加不同的函式
group_cols = ['ORG_AIR', 'DEST_AIR']
agg_dict = {'CANCELLED':['sum', 'mean', 'size'],
      'AIR_TIME':['mean', 'var']}
flights.groupby(group_cols).agg(agg_dict).head()

#下面這個例子中,max_deviation是自定義的函式
def max_deviation(s):
  std_score = (s - s.mean()) / s.std()
  return std_score.abs().max()     
college.groupby('STABBR')['UGDS'].agg(max_deviation).round(1).head()
grouped = college.groupby(['STABBR', 'RELAFFIL'])
grouped.ngroups# 用ngroups屬性檢視分組的數量
list(grouped.groups.keys())

需要用到的常見方法和含義如下:

方法含義
aggregate() 為每個組獲取一個值
filter() 獲取輸入行的子集
transform() 為每個輸入行獲取新值
apply() 對某一列實施複雜操作

基本畫圖

Matplotlib提供了兩種方法來作圖:
面向過程和麵向物件,可以根據需要選擇。

Matplotlib常見畫圖過程如下:

x = [-3, 5, 7]
y = [10, 2, 5]
fig, ax = plt.subplots(figsize=(15,3))
ax.plot(x, y)
ax.set_xlim(0, 10)
ax.set_ylim(-3, 8)
ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_title('Line Plot')
fig.suptitle('Figure Title', size=20, y=1.03)

pandas畫圖如下:

df = pd.DataFrame(index=['Atiya', 'Abbas', 'Cornelia', 'Stephanie', 'Monte'],data={'Apples':[20, 10, 40, 20, 50],'Oranges':[35, 40, 25, 19, 33]})
color = ['.2', '.7']
df.plot(kind='bar', color=color, figsize=(16,4))

fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(16,4))
fig.suptitle('Two Variable Plots', size=20, y=1.02)
df.plot(kind='line', color=color, ax=ax1, title='Line plot')
df.plot(x='Apples', y='Oranges', kind='scatter', ax=ax2, title='Scatterplot')
df.plot(kind='bar', color=color, ax=ax3, title='Bar plot')

如下:

還可以使用seaborn畫圖,如下:

import seaborn as sns
sns.heatmap(crime_table, cmap='Greys')

二、簡單分析College資料

新建college_data目錄,下放College.csv如下:

如需獲取資料、程式碼等相關檔案進行測試學習,可以直接點選加QQ群​963624318在群資料夾Python資料分析實戰中下載即可。

先讀取和預覽資料:

import pandas as pd
import numpy as np
from IPython.display import display

pd.options.display.max_columns = 50

college = pd.read_csv('College.csv')
college.head()

顯示:

獲取所有列名:

columns=college.columns
columns

列印:

Index(['Name', 'Private', 'Apps', 'Accept', 'Enroll', 'Top10perc', 'Top25perc', 'F.Undergrad', 'P.Undergrad', 'Outstate', 'Room.Board', 'Books', 'Personal', 'PhD', 'Terminal', 'S.F.Ratio', 'perc.alumni', 'Expend', 'Grad.Rate'], dtype='object')

選擇資料子集:

print(college.iloc[:, [4,6]].head( )) # 選取4、6列的所有行

s1=college.loc[:, ['PhD', 'Books']]
s1.head()

顯示:

一般在jupyter的一個cell中只預設輸出最後一行的變數,要想輸出前面行的資料,需要呼叫print()方法。

設定索引:

index=college.iloc[[60, 99, 3]].index.tolist() # .index.tolist()可以直接提取索引標籤,生成一個列表

print(index)
college = college.set_index('Name',drop=False)
index2=college.iloc[[60, 99, 3]].index.tolist()
print(index2)

列印:

[60, 99, 3]
['Bowdoin College', 'Centenary College of Louisiana', 'Agnes Scott College']

顯然,在設定索引之前,索引預設為數字索引,在設定索引為Name之後,索引也相應發生變化。
其中,set_index()方法如果不設定drop引數,在將Name設為索引後,就將該列移除了,不能再重複執行這一行程式碼,否則會報錯,設定drop引數為False後,設定Name為索引後也不會移除該列。

根據索引位置獲取值如下:

col3 =college.loc['Albion College','Top10perc']  
col3

列印:

37

這與資料中的值一致。

逐行讀取如下:

s4=college[10:20:2]# 逐行讀取,跨行讀取
print(s4)
seriesapps = college['Apps'] 
seriesapps[1:10:2] # Series也可以進行同樣的切片

顯示:

其中,college[10:20:2]是對資料進行逐行讀取,從第11行開始到21行,每隔一行讀取一行資料。

檢視索引如下:

college.index

列印:

Index(['Abilene', 'Adelphi University', 'Adrian College',
       'Agnes Scott College', 'Alaska Pacific University', 'Albertson College',
       'Albertus Magnus College', 'Albion College', 'Albright College',
       'Alderson-Broaddus College',
       ...
       'Winthrop University', 'Wisconsin Lutheran College',
       'Wittenberg University', 'Wofford College',
       'Worcester Polytechnic Institute', 'Worcester State College',
       'Xavier University', 'Xavier University of Louisiana',
       'Yale University', 'York College of Pennsylvania'],
      dtype='object', name='Name', length=777)

完整操作過程如下:

三、鳶尾花資料集分析

新建iris_data資料夾,存放iris.csv。

鳶尾花Iris資料如下:

如需獲取資料、程式碼等相關檔案進行測試學習,可以直接點選加QQ群​963624318在群資料夾Python資料分析實戰中下載即可。

1.基礎操作

資料的基本操作步驟如下:
(1)讀取資料:

import pandas as pd
import numpy as np
iris_data = pd.read_csv("iris.csv",header=0,
names = ["花萼長度", "花萼寬度", "花瓣長度", "花瓣寬度", "類別"],
encoding = 'gbk');
pd.set_option("display.max_rows", 5) # 設定最大顯示5行資料
iris_data.head()

顯示:

(2)對資料進行切片刪除

iris_data[:50]
DataFrame = iris_data[:5].copy() # 建立資料副本,以便多次修改
DataFrame.drop(index=[1,3])

顯示:

顯然,刪除了第一行和第三行,這與

DataFrame = iris_data[:5].copy() # 建立資料副本,以便多次修改
DataFrame.drop(columns=["花萼寬度", "花瓣寬度"])

不同,顯示:

刪除的是指定列。

還可以既 刪除行、又刪除列,如下:

DataFrame = iris_data[:5].copy() # 建立資料副本,以便多次修改
DataFrame.drop(index=[1,3],columns=["花萼寬度", "花瓣寬度"])

顯示:

(3)基本賦值
可以通過多種方式賦值,如下:

DataFrame = iris_data[:5].copy() # 建立資料副本,以便多次修改
DataFrame.loc[1, "類別"] = "新類別名" # 修改第0行類別標籤列的資料
print(DataFrame)
DataFrame = iris_data[:5].copy() # 建立資料副本,以便多次修改
DataFrame.loc[1] = "新資料" # 修改第1行的資料
print(DataFrame)
DataFrame = iris_data[:5].copy() # 建立資料副本,以便多次修改
DataFrame.loc[:, "花萼長度"] = 10 # 修改第1列的資料
print(DataFrame)

列印:

花萼長度  花萼寬度  花瓣長度  花瓣寬度      類別
1   5.1   3.5   1.4   0.2    新類別名
2   4.9   3.0   1.4   0.2  setosa
3   4.7   3.2   1.3   0.2  setosa
4   4.6   3.1   1.5   0.2  setosa
5   5.0   3.6   1.4   0.2  setosa
  花萼長度 花萼寬度 花瓣長度 花瓣寬度      類別
1  新資料  新資料  新資料  新資料     新資料
2  4.9    3  1.4  0.2  setosa
3  4.7  3.2  1.3  0.2  setosa
4  4.6  3.1  1.5  0.2  setosa
5    5  3.6  1.4  0.2  setosa
   花萼長度  花萼寬度  花瓣長度  花瓣寬度      類別
1    10   3.5   1.4   0.2  setosa
2    10   3.0   1.4   0.2  setosa
3    10   3.2   1.3   0.2  setosa
4    10   3.1   1.5   0.2  setosa
5    10   3.6   1.4   0.2  setosa

(4)索引檢索
index檢索iloc[]是左閉右開,如DataFrame.iloc[1:3, 1]選擇第一二行的第一列,如下:

print(DataFrame.iloc[-1]) # 最後一行
print(DataFrame.iloc[1:3, 1]) # 第一二行的第1列

print('----')
print(DataFrame.iloc[1:3, 1:3])
print(DataFrame.iloc[:3, :3]) # 前三行的前三列
print(DataFrame.iloc[[0,1,3], 1]) # 第0,1,3行的第1列
print(DataFrame.iloc[[True, False, True, False, False]]) # 第0,2行

列印:

花萼長度        10
花萼寬度       3.6
花瓣長度       1.4
花瓣寬度       0.2
類別      setosa
Name: 5, dtype: object
2    3.0
3    3.2
Name: 花萼寬度, dtype: float64
----
   花萼寬度  花瓣長度
2   3.0   1.4
3   3.2   1.3
   花萼長度  花萼寬度  花瓣長度
1    10   3.5   1.4
2    10   3.0   1.4
3    10   3.2   1.3
1    3.5
2    3.0
4    3.1
Name: 花萼寬度, dtype: float64
   花萼長度  花萼寬度  花瓣長度  花瓣寬度      類別
1    10   3.5   1.4   0.2  setosa
3    10   3.2   1.3   0.2  setosa

可以看到,iloc[]的使用很靈活。

還可以用label檢索,使用loc[]方法,是左閉右閉,如下:

# DataFrame.loc[-1] # 語法錯誤!!!
print(DataFrame.loc[1]) # 第0行
print(DataFrame.loc[:, "花萼長度"]) # 所有行的“花萼長度”列
print(DataFrame.loc[[1,3], "類別"]) # 第0,1,3行的“類別”列
print(DataFrame.loc[[True, False, True, False, False]]) # 第0,2行

列印:

花萼長度        10
花萼寬度       3.5
花瓣長度       1.4
花瓣寬度       0.2
類別      setosa
Name: 1, dtype: object
1    10
2    10
3    10
4    10
5    10
Name: 花萼長度, dtype: int64
1    setosa
3    setosa
Name: 類別, dtype: object
   花萼長度  花萼寬度  花瓣長度  花瓣寬度      類別
1    10   3.5   1.4   0.2  setosa
3    10   3.2   1.3   0.2  setosa

注意:
loc[]方法使用數字索引時不能從0開始,因為一般自帶的索引是從1到length,而不是0到length-1,需與前者保持一致,並且也不能使用-1索引,可以使用length。

(5)條件檢索
比較條件檢索如下:

DataFrame["花萼長度"] = pd.to_numeric(DataFrame["花萼長度"], errors='coerce')

s1=DataFrame.loc[DataFrame["花萼長度"]>4]
print(s1)
s2=DataFrame.loc[(DataFrame["花萼長度"]>=5.0) & (DataFrame["花瓣長度"]>=1.4)]
s2

顯示:

判斷為空和不為空用isnull()notnull(),如下:

df = iris_data.loc[iris_data["花萼長度"].isnull()]
print(df[:4])
df = iris_data.loc[iris_data["類別"].notnull()]
print(df[:5])

列印:

Empty DataFrame
Columns: [花萼長度, 花萼寬度, 花瓣長度, 花瓣寬度, 類別]
Index: []
   花萼長度  花萼寬度  花瓣長度  花瓣寬度      類別
1   5.1   3.5   1.4   0.2  setosa
2   4.9   3.0   1.4   0.2  setosa
3   4.7   3.2   1.3   0.2  setosa
4   4.6   3.1   1.5   0.2  setosa
5   5.0   3.6   1.4   0.2  setosa

判斷值是否在某個集合用isin(),如下:

df = iris_data.loc[iris_data["花萼長度"].isin([5.0, 4.7])]
df[:5]

顯示:

(6)條件統計
如下:

print(iris_data.loc[iris_data["類別"] == "versicolor"].count())
c1 = sum(iris_data["類別"] == "setosa")
c2 = sum(iris_data["類別"] == "versicolor")
c3 = sum(iris_data["類別"] == "virginica")
print(c1, c2, c3) # 手動統計各類樣本數量
iris_data["類別"].value_counts()

列印:

花萼長度    50
花萼寬度    50
花瓣長度    50
花瓣寬度    50
類別      50
dtype: int64
50 0 0

virginica     50
versicolor    50
setosa        50
Name: 類別, dtype: int64

(7)條件賦值
對某一列資料複製如下:

DataFrame = iris_data[:5].copy() # 建立資料副本,以便多次修改
DataFrame.loc[DataFrame["花萼長度"]>4.8, "類別"] = "大花萼"
DataFrame

列印:

花萼長度 	花萼寬度 	花瓣長度 	花瓣寬度 	類別
1 	5.1 	3.5 	1.4 	0.2 	大花萼
2 	4.9 	3.0 	1.4 	0.2 	大花萼
3 	4.7 	3.2 	1.3 	0.2 	setosa
4 	4.6 	3.1 	1.5 	0.2 	setosa
5 	5.0 	3.6 	1.4 	0.2 	大花萼

對所有列資料進行賦值如下:

DataFrame = iris_data[:5].copy() # 建立資料副本,以便多次修改
DataFrame.loc[DataFrame["花萼長度"]>4.8] = "錯誤資料"
DataFrame

列印:

花萼長度 	花萼寬度 	花瓣長度 	花瓣寬度 	類別
1 	錯誤資料 	錯誤資料 	錯誤資料 	錯誤資料 	錯誤資料
2 	錯誤資料 	錯誤資料 	錯誤資料 	錯誤資料 	錯誤資料
3 	4.7 	3.2 	1.3 	0.2 	setosa
4 	4.6 	3.1 	1.5 	0.2 	setosa
5 	錯誤資料 	錯誤資料 	錯誤資料 	錯誤資料 	錯誤資料

(8)缺失值處理
判斷缺失值:

print(iris_data.isnull())
print(iris_data.isnull().sum())

列印:

花萼長度   花萼寬度   花瓣長度   花瓣寬度     類別
1    False  False  False  False  False
2    False  False  False  False  False
..     ...    ...    ...    ...    ...
149  False  False  False  False  False
150  False  False  False  False  False

[150 rows x 5 columns]
花萼長度    0
花萼寬度    0
花瓣長度    0
花瓣寬度    0
類別      0
dtype: int64

指定單一值填充缺失值:

iris_data.fillna('Unknown')
iris_data["花萼長度"].fillna('Unknown')

列印:

1      5.1
2      4.9
      ... 
149    6.2
150    5.9
Name: 花萼長度, Length: 150, dtype: float64

根據列指定不同的值填充缺失值:

mean = iris_data['花萼寬度'].mean()     # 平均數
median = iris_data['花瓣長度'].median() # 中位數
mode = iris_data['花萼寬度'].mode()     # 眾數
values = {'花萼長度': 0, '花萼寬度': mean, '花瓣長度': 2, '花萼寬度': mode}
iris_data.fillna(value=values)

列印:

花萼長度 	花萼寬度 	花瓣長度 	花瓣寬度 	類別
1 	5.1 	3.5 	1.4 	0.2 	setosa
2 	4.9 	3.0 	1.4 	0.2 	setosa
... 	... 	... 	... 	... 	...
149 	6.2 	3.4 	5.4 	2.3 	virginica
150 	5.9 	3.0 	5.1 	1.8 	virginica

150 rows × 5 columns

移除缺失值如下:

iris_data.dropna() # 去掉含缺失項的行
iris_data.dropna(axis='columns') # 去掉含缺失項的列
iris_data.dropna(how='all') # 去掉所有項均缺失的行
iris_data.dropna(thresh=2) # 去掉多於2個缺失項的行

列印:

花萼長度 	花萼寬度 	花瓣長度 	花瓣寬度 	類別
1 	5.1 	3.5 	1.4 	0.2 	setosa
2 	4.9 	3.0 	1.4 	0.2 	setosa
... 	... 	... 	... 	... 	...
149 	6.2 	3.4 	5.4 	2.3 	virginica
150 	5.9 	3.0 	5.1 	1.8 	virginica

150 rows × 5 columns

替換值:

df = iris_data.replace(5.0, 50) # 預設為深複製,保護原資料
df['花萼寬度'] = df['花萼寬度'].replace(3.5, 30.5)
df = df.replace([0, 1, 2, 3], 4)
df = df.replace([0, 1, 2, 3], [4, 3, 2, 1])
df = df.replace({'花萼長度':5.1, '花瓣長度':5.1}, 5)
df = df.replace({'花瓣長度' : {5.1:5.0, 6.2:6.0}})
df.head()

列印:

花萼長度 	花萼寬度 	花瓣長度 	花瓣寬度 	類別
1 	5.0 	30.5 	1.4 	0.2 	setosa
2 	4.9 	4.0 	1.4 	0.2 	setosa
3 	4.7 	3.2 	1.3 	0.2 	setosa
4 	4.6 	3.1 	1.5 	0.2 	setosa
5 	50.0 	3.6 	1.4 	0.2 	setosa

2.資料分析

描述統計如下:

iris_data["類別"].describe()

列印:

count           150
unique            3
top       virginica
freq             50
Name: 類別, dtype: object

列印:

count           150
unique            3
top       virginica
freq             50
Name: 類別, dtype: object

計數:

print(iris_data["類別"].count())

列印:

150

求所有列的最大值和指定列的最大值:

print(iris_data.max())
print(iris_data["花萼長度"].max())

列印:

花萼長度          7.9
花萼寬度          4.4
花瓣長度          6.9
花瓣寬度          2.5
類別      virginica
dtype: object
7.9

求所有列的最小值和指定列的最小值:

print(iris_data.min())
print(iris_data["花萼長度"].min())

列印:

花萼長度       4.3
花萼寬度         2
花瓣長度         1
花瓣寬度       0.1
類別      setosa
dtype: object
4.3

求所有列的平均值和指定列的平均值:

print(iris_data.mean())
print(iris_data["花萼長度"].mean())

列印:

花萼長度    5.843333
花萼寬度    3.057333
花瓣長度    3.758000
花瓣寬度    1.199333
dtype: float64
5.843333333333335

求所有列的中位數和指定列的中位數:

print(iris_data.median())
print(iris_data["花萼長度"].median())

列印:

花萼長度    5.80
花萼寬度    3.00
花瓣長度    4.35
花瓣寬度    1.30
dtype: float64
5.8

列出某一列的所有不同值:

iris_data["類別"].unique() # 列出所有不同的取值

列印:

array(['setosa', 'versicolor', 'virginica'], dtype=object)

對值進行升序排列:

np.sort(iris_data["花萼長度"].unique()) # 預設升序排列

列印:

array([4.3, 4.4, 4.5, 4.6, 4.7, 4.8, 4.9, 5. , 5.1, 5.2, 5.3, 5.4, 5.5,
       5.6, 5.7, 5.8, 5.9, 6. , 6.1, 6.2, 6.3, 6.4, 6.5, 6.6, 6.7, 6.8,
       6.9, 7. , 7.1, 7.2, 7.3, 7.4, 7.6, 7.7, 7.9])

聚合函式,對不同資料進行多維度統計:

iris0=iris_data.agg(['max', 'min', 'mean', 'median']) # agg聚合操作,可執行多個函式
iris0

列印:

花萼長度 	花萼寬度 	花瓣長度 	花瓣寬度 	類別
max 	7.900000 	4.400000 	6.900 	2.500000 	virginica
min 	4.300000 	2.000000 	1.000 	0.100000 	setosa
mean 	5.843333 	3.057333 	3.758 	1.199333 	NaN
median 	5.800000 	3.000000 	4.350 	1.300000 	NaN

對某一列進行聚合函式操作:

iris1=iris_data["花萼長度"].agg(['max', 'min', 'mean', 'median'])
iris1

列印:

max       7.900000
min       4.300000
mean      5.843333
median    5.800000
Name: 花萼長度, dtype: float64

對某一列進行分組並計數:

iris2=iris_data.groupby(['花萼長度'])['花萼長度'].count() # 分組,花萼長度由小到大排列
iris2

列印:

花萼長度
4.3    1
4.4    3
      ..
7.7    4
7.9    1
Name: 花萼長度, Length: 35, dtype: int64

對分組後的資料進行聚合函式操作:

iris_data_review = iris_data.groupby(['花萼長度'])['花瓣寬度'].agg(['min', 'max']) # 分組
iris_data_review

列印:

min 	max
花萼長度 		
4.3 	0.1 	0.1
4.4 	0.2 	0.2
... 	... 	...
7.7 	2.0 	2.3
7.9 	2.0 	2.0

35 rows × 2 columns

最後儲存資料:

iris_data.to_csv("newdata.csv", na_rep="NA", index = False, encoding='gbk')
iris_data = pd.read_csv("newdata.csv", encoding = "gbk");
iris_data.head()

列印:

花萼長度 	花萼寬度 	花瓣長度 	花瓣寬度 	類別
0 	5.1 	3.5 	1.4 	0.2 	setosa
1 	4.9 	3.0 	1.4 	0.2 	setosa
2 	4.7 	3.2 	1.3 	0.2 	setosa
3 	4.6 	3.1 	1.5 	0.2 	setosa
4 	5.0 	3.6 	1.4 	0.2 	setosa

完整過程如下:

四、電影評分資料分析

對電影資料的分析主要包括以下方面:

  • 平均分較高的電影
  • 不同性別對電影平均評分
  • 男女觀眾區別最大電影
  • 評分次數最多熱門的電影
  • 不同年齡段區別最大的電影

新建movie_data目錄用於儲存電影相關資料。
電影評分資料主要包括3組資料:
users.dat使用者資料如下:

movies.dat電影資料如下:

ratings.dat評分資料如下:

可以看到,三組資料的每一行都類似1::F::1::10::48067,需要通過雙冒號分隔成不同的資料列。

基本操作步驟如下:
(1)導包和資料
先匯入所需要的庫,如下:

import numpy as np

import pandas as pd

from pandas import Series,DataFrame

# 畫圖
import matplotlib.pyplot as plt
%matplotlib inline

再匯入使用者資料:

# 讀取user使用者
# UserID::Gender::Age::Occupation::Zip-code
labels = ['UserId','Gender','Age','Occupation','zip-code']

users = pd.read_csv('users.dat',sep = '::',header = None,names = labels, engine='python')
index = users.index
data = users.values
display(users.shape,index,data)

列印:

(6040, 5)

RangeIndex(start=0, stop=6040, step=1)

array([[1, 'F', 1, 10, '48067'],
       [2, 'M', 56, 16, '70072'],
       [3, 'M', 25, 15, '55117'],
       ...,
       [6038, 'F', 56, 1, '14706'],
       [6039, 'F', 45, 0, '01060'],
       [6040, 'M', 25, 6, '11106']], dtype=object)

易知,有6040條資料,每條資料5個屬性值。

檢視使用者資料:

users.head()

列印:

UserId 	Gender 	Age 	Occupation 	zip-code
0 	1 	F 	1 	10 	48067
1 	2 	M 	56 	16 	70072
2 	3 	M 	25 	15 	55117
3 	4 	M 	45 	7 	02460
4 	5 	M 	25 	20 	55455

讀取電影資料如下:

# movie
# MovieID::Title::Genres
labels = ['MovieId','Title','Genres']

movie = pd.read_csv('movies.dat',sep = '::',header = None,names = labels, engine='python')

display(movie.head(),movie.shape)

列印:

MovieId 	Title 	Genres
0 	1 	Toy Story (1995) 	Animation|Children's|Comedy
1 	2 	Jumanji (1995) 	Adventure|Children's|Fantasy
2 	3 	Grumpier Old Men (1995) 	Comedy|Romance
3 	4 	Waiting to Exhale (1995) 	Comedy|Drama
4 	5 	Father of the Bride Part II (1995) 	Comedy

(3883, 3)

電影資料共有3883條,每條3個屬性;
display()函式可以使用者同時展示多個數據。

讀取評分資料如下:

# 評分
# UserID::MovieID::Rating::Timestamp
labels = ['UserId','MovieId','Rating','Time']

ratings = pd.read_csv('./ratings.dat',sep = '::',header = None,names = labels, engine='python')
display(ratings.head(),ratings.shape)

列印:

UserId 	MovieId 	Rating 	Time
0 	1 	1193 	5 	978300760
1 	1 	661 	3 	978302109
2 	1 	914 	3 	978301968
3 	1 	3408 	4 	978300275
4 	1 	2355 	5 	978824291

(1000209, 4)

電影資料共有1000209條,每條3個屬性;
因為資料量較大,因此執行稍有延遲。

(2)資料合併
需要將三張表進行合併。

先檢視三張表:

#三個表
display(users.head(),movie.head(),ratings.head())

顯示:

先合併電影表和評分表:

df1 = pd.merge(left = movie,right=ratings)
df1.head()

顯示:

電影表和評分表之所以可以合併,是因為這兩張表中都有MovieId屬性,可以作為兩張表的關聯屬性,類似於SQL資料庫中將兩張表進行關聯時需要外來鍵。

同理,將df1與使用者表進行合併:

movie_data = pd.merge(df1,users)
movie_data.head()

顯示:

同樣,df1可以和users表合併,是因為這兩張表都有UserId作為關聯屬性。

(3)檢視資料
檢視movie_data表的規模:

movie_data.shape

列印:

(1000209, 10)

顯然,合併後的表有3個屬性。

檢視Age屬性的唯一值:

movie_data['Age'].unique()

列印:

array([ 1, 50, 25, 35, 18, 45, 56], dtype=int64)

可以看到,共有7個唯一的值。

檢視Title唯一值的個數:

movie_data['Title'].unique().size   # 檢視有多少部電影

列印:

3706

即有3706部電影。

(4)獲取平均分較高的電影
先求出每部電影的平均評分如下:

#以title 作為index 對資料進行劃分
movie_rate_pingjun = pd.pivot_table(movie_data,values=['Rating'],index = ['Title'],aggfunc='mean')
movie_rate_pingjun.shape

列印:

(3706, 1)

可以看到,是呼叫Pandas的pivot_table()透視表方法、並傳遞平均值作為聚合函式求出每部電影的平均評分的。

檢視平均評分情況:

movie_rate_pingjun.head()

顯示:

對平均評分進行降序排列:

movie_rate_pingjun.sort_values(by = 'Rating',ascending=False,inplace=False)

顯示:

獲取movie_data表中前20和後20條資料如下:

display(movie_rate_pingjun[:20],movie_rate_pingjun[-20:])

顯示:

(5)不同性別對電影的平均評分
現根據電影名和性別計算平均評分如下:

# 透視表,透視資料結構 ,兩個index 
movie_gender_rating_pingjun = pd.pivot_table(movie_data,values=['Rating'],index=['Title','Gender'],aggfunc='mean')
movie_rate_pingjun.shape

列印:

(3706, 1)

檢視平均評分結果如下:

movie_gender_rating_pingjun.head()  # dataframe

顯示:

可以看到,相當於是進行了兩次分組,先對電影名進行分組,在電影名相同的情況下再對姓名進行分組,並計算出相應的平均評分。

下面兩種形式又有所不同:

#去掉中括號 ,
movie_gender_rating_pingjun0 = pd.pivot_table(movie_data,values=['Rating'],index=['Title'],columns=['Gender'],aggfunc='mean')

movie_gender_rating_pingjun = pd.pivot_table(movie_data,values='Rating',index=['Title'],columns=['Gender'],aggfunc='mean')

display(movie_gender_rating_pingjun0.shape, movie_gender_rating_pingjun0.head(),movie_gender_rating_pingjun.shape,movie_gender_rating_pingjun.head())

顯示:

顯然,表格表現上有所區別。

(6)不同性別區別最大電影的排序
先檢視movie_gender_rating_pingjun表的列:

movie_gender_rating_pingjun.columns

列印:

Index(['F', 'M'], dtype='object', name='Gender')

再增加一列資料為男女平均評分的差值:

# 女性使用者和男性使用者對定影評分差異 ,給資料集增加一列
movie_gender_rating_pingjun['diff'] = movie_gender_rating_pingjun.F - movie_gender_rating_pingjun.M
movie_gender_rating_pingjun.head()

顯示:

再對評分差異排序:

# 排序sort_values,是pandas常用的方法
movie_gender_rating_pingjun.sort_values(by = 'diff',ascending=False,inplace=True)
movie_gender_rating_pingjun.head()

顯示:

可以看到,性別差異最大的5部電影。

因為越排在前面,表示女性比男性越多,可以表示女性越喜歡、男性越不喜歡,檢視前10如下:

# 女性使用者和男性使用者差異最大,女性用最喜歡 ,前10名
female = movie_gender_rating_pingjun[:10]
female

顯示:

同樣,排在越靠後,表示男性越喜歡、女性越不喜歡,排名前10如下:

#男性使用者最喜歡的 ,去除女性使用者評分空資料
print(movie_gender_rating_pingjun[-10:])  #有空值
male = movie_gender_rating_pingjun.dropna()[-10:]
male

顯示:

再連線女性最喜歡的前10和男性最喜歡的前10:

diff = pd.concat([female,male]) # 連線兩個資料集
diff

顯示:

再對連線後的資料畫圖:

# 分析結果資料視覺化,barh水平的柱狀圖  x 橫座標,標題, y 縱座標 
diff.plot(y = 'diff' ,kind = 'barh',figsize=(12,9),color= 'green')

顯示:

可以直觀地將男性和女性最喜歡的電影展示出來。

(7)獲取評分次數最多熱門的電影
先檢視movie_data.shape的資料概況:

movie_data.shape

列印:

(1000209, 10)

根據電影標題對資料分組:

# pandas分組運算
rating_count = movie_data.groupby(['Title']).size()
rating_count.sort_values(ascending=False)[:50]

列印:

Title
American Beauty (1999)                                   3428
Star Wars: Episode IV - A New Hope (1977)                2991
Star Wars: Episode V - The Empire Strikes Back (1980)    2990
Star Wars: Episode VI - Return of the Jedi (1983)        2883
Jurassic Park (1993)                                     2672
Saving Private Ryan (1998)                               2653
Terminator 2: Judgment Day (1991)                        2649
Matrix, The (1999)                                       2590
Back to the Future (1985)                                2583
Silence of the Lambs, The (1991)                         2578
Men in Black (1997)                                      2538
Raiders of the Lost Ark (1981)                           2514
Fargo (1996)                                             2513
Sixth Sense, The (1999)                                  2459
Braveheart (1995)                                        2443
Shakespeare in Love (1998)                               2369
Princess Bride, The (1987)                               2318
Schindler's List (1993)                                  2304
L.A. Confidential (1997)                                 2288
Groundhog Day (1993)                                     2278
E.T. the Extra-Terrestrial (1982)                        2269
Star Wars: Episode I - The Phantom Menace (1999)         2250
Being John Malkovich (1999)                              2241
Shawshank Redemption, The (1994)                         2227
Godfather, The (1972)                                    2223
Forrest Gump (1994)                                      2194
Ghostbusters (1984)                                      2181
Pulp Fiction (1994)                                      2171
Terminator, The (1984)                                   2098
Toy Story (1995)                                         2077
Alien (1979)                                             2024
Total Recall (1990)                                      1996
Fugitive, The (1993)                                     1995
Gladiator (2000)                                         1924
Aliens (1986)                                            1820
Blade Runner (1982)                                      1800
Who Framed Roger Rabbit? (1988)                          1799
Stand by Me (1986)                                       1785
Usual Suspects, The (1995)                               1783
Babe (1995)                                              1751
Airplane! (1980)                                         1731
Independence Day (ID4) (1996)                            1730
Galaxy Quest (1999)                                      1728
One Flew Over the Cuckoo's Nest (1975)                   1725
Wizard of Oz, The (1939)                                 1718
2001: A Space Odyssey (1968)                             1716
Abyss, The (1989)                                        1715
Bug's Life, A (1998)                                     1703
Jaws (1975)                                              1697
Godfather: Part II, The (1974)                           1692
dtype: int64

可以獲取到每部電影被評論的次數。

(8)檢視不同年齡段差別最大的電影
先檢視使用者的年齡分佈:

movie_data['Age'].plot(kind = 'hist',bins = 30) #橫座標年齡段 
  • 1

顯示:

再獲取最大年齡:

movie_data.Age.max()  # 最大年齡

列印:

56

再用pandas.cut函式將使用者年齡分組:

labels = ['0-9','10-19','20-29','30-39','40-49','50-59']

movie_data['Age_range'] = pd.cut(movie_data.Age,bins = range(0,61,10),labels=labels)

movie_data.head()

顯示:

可以看到多了一個欄位年齡段。

此時再檢視不同年齡段各資料的均值:

movie_data.groupby('Age_range').mean()

顯示:

檢視各年齡段的人數和評分均值:

movie_data.groupby('Age_range').agg({'Rating':[np.size,np.mean]})

顯示:

(9)加入評分次數限制的分析不同性別對電影的平均評分
檢視平均評分前10的電影:

#看平均分的前10個數據,發現很大都不知道的電影。
movie_rate_pingjun[:10]

顯示:

可以看到,很多電影年代久遠、不出名還評分比較高,可能存在人為因素,比如評分人數很少、但是評分較高(可能由內部人員評分等),因此產生了噪聲、導致結果不準確,因此需要加上評分次數的限制。

檢視性別與平均評分如下:

display(movie_gender_rating_pingjun.index, movie_gender_rating_pingjun.head())
  • 1

顯示:

在對電影評分數進行排名,獲取前100:

 movie_data.groupby('Title').size().sort_values()[::-1][:100]

列印:

Title
American Beauty (1999)                                   3428
Star Wars: Episode IV - A New Hope (1977)                2991
Star Wars: Episode V - The Empire Strikes Back (1980)    2990
Star Wars: Episode VI - Return of the Jedi (1983)        2883
Jurassic Park (1993)                                     2672
                                                         ... 
Christmas Story, A (1983)                                1352
Aladdin (1992)                                           1351
Romancing the Stone (1984)                               1345
Blues Brothers, The (1980)                               1341
Rock, The (1996)                                         1340
Length: 100, dtype: int64

獲取評分次數前100的電影名單:

#對觀影次數做排序,獲取索引
top_movie_title = movie_data.groupby('Title').size().sort_values()[::-1][:100].index
top_movie_title

列印:

Index(['American Beauty (1999)', 'Star Wars: Episode IV - A New Hope (1977)',
       'Star Wars: Episode V - The Empire Strikes Back (1980)',
       'Star Wars: Episode VI - Return of the Jedi (1983)',
       'Jurassic Park (1993)', 'Saving Private Ryan (1998)',
       'Terminator 2: Judgment Day (1991)', 'Matrix, The (1999)',
       'Back to the Future (1985)', 'Silence of the Lambs, The (1991)',
       'Men in Black (1997)', 'Raiders of the Lost Ark (1981)', 'Fargo (1996)',
       'Sixth Sense, The (1999)', 'Braveheart (1995)',
       'Shakespeare in Love (1998)', 'Princess Bride, The (1987)',
       'Schindler's List (1993)', 'L.A. Confidential (1997)',
       'Groundhog Day (1993)', 'E.T. the Extra-Terrestrial (1982)',
       'Star Wars: Episode I - The Phantom Menace (1999)',
       'Being John Malkovich (1999)', 'Shawshank Redemption, The (1994)',
       'Godfather, The (1972)', 'Forrest Gump (1994)', 'Ghostbusters (1984)',
       'Pulp Fiction (1994)', 'Terminator, The (1984)', 'Toy Story (1995)',
       'Alien (1979)', 'Total Recall (1990)', 'Fugitive, The (1993)',
       'Gladiator (2000)', 'Aliens (1986)', 'Blade Runner (1982)',
       'Who Framed Roger Rabbit? (1988)', 'Stand by Me (1986)',
       'Usual Suspects, The (1995)', 'Babe (1995)', 'Airplane! (1980)',
       'Independence Day (ID4) (1996)', 'Galaxy Quest (1999)',
       'One Flew Over the Cuckoo's Nest (1975)', 'Wizard of Oz, The (1939)',
       '2001: A Space Odyssey (1968)', 'Abyss, The (1989)',
       'Bug's Life, A (1998)', 'Jaws (1975)', 'Godfather: Part II, The (1974)',
       'Casablanca (1942)', 'Die Hard (1988)', 'GoodFellas (1990)',
       'Hunt for Red October, The (1990)', 'Speed (1994)',
       'Indiana Jones and the Last Crusade (1989)', 'Lethal Weapon (1987)',
       'Monty Python and the Holy Grail (1974)', 'Toy Story 2 (1999)',
       'When Harry Met Sally... (1989)', 'Good Will Hunting (1997)',
       'Titanic (1997)', 'Breakfast Club, The (1985)',
       'Mission: Impossible (1996)', 'Election (1999)', 'X-Men (2000)',
       'Twelve Monkeys (1995)', 'Beetlejuice (1988)', 'Big (1988)',
       'Ferris Bueller's Day Off (1986)', 'Edward Scissorhands (1990)',
       'Close Encounters of the Third Kind (1977)', 'Fight Club (1999)',
       'Dances with Wolves (1990)', 'Star Trek: The Wrath of Khan (1982)',
       'Raising Arizona (1987)',
       'Austin Powers: The Spy Who Shagged Me (1999)', 'Batman (1989)',
       'As Good As It Gets (1997)', 'Face/Off (1997)',
       'Butch Cassidy and the Sundance Kid (1969)', 'Thelma & Louise (1991)',
       'Clerks (1994)', 'True Lies (1994)', 'American Pie (1999)',
       'Contact (1997)', 'Amadeus (1984)', 'Fifth Element, The (1997)',
       'High Fidelity (2000)', 'There's Something About Mary (1998)',
       'Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb (1963)',
       'Arachnophobia (1990)', 'Clueless (1995)', 'Get Shorty (1995)',
       'Jerry Maguire (1996)', 'Christmas Story, A (1983)', 'Aladdin (1992)',
       'Romancing the Stone (1984)', 'Blues Brothers, The (1980)',
       'Rock, The (1996)'],
      dtype='object', name='Title')

判斷每一部電影是否在評分次數前100的名單中:

flag = movie_gender_rating_pingjun.index.isin(top_movie_title)
flag

列印:

array([False, False, False, ..., False, False, False])

根據男女之間的差別對列表中的電影排序(升序):

df1 = movie_gender_rating_pingjun[flag].sort_values(by = 'diff') # 比較好的電影男女都喜歡
df1

顯示:

畫圖:

df1.plot(kind = 'barh',figsize=(12,9))

顯示:

顯然,很直觀。

(10)加入評分次數限制但不區分性別的分析平均分高的電影
前面是包括了性別區別在內的電影評分資料,這裡不加入性別因素來考慮。

先獲取到電影平均評分資料:

movie_rating_mean = pd.pivot_table(movie_data,values='Rating',index=['Title'])
movie_rating_mean

顯示:

獲取評分次數前100的電影:

#::-1 對資料做切片,倒序  最受歡迎的電影 獲取index
top_movie_title2 = movie_data.groupby('Title').size().sort_values()[::-1][:100].index
top_movie_title2

列印:

Index(['American Beauty (1999)', 'Star Wars: Episode IV - A New Hope (1977)',
       'Star Wars: Episode V - The Empire Strikes Back (1980)',
       'Star Wars: Episode VI - Return of the Jedi (1983)',
       'Jurassic Park (1993)', 'Saving Private Ryan (1998)',
       'Terminator 2: Judgment Day (1991)', 'Matrix, The (1999)',
       'Back to the Future (1985)', 'Silence of the Lambs, The (1991)',
       'Men in Black (1997)', 'Raiders of the Lost Ark (1981)', 'Fargo (1996)',
       'Sixth Sense, The (1999)', 'Braveheart (1995)',
       'Shakespeare in Love (1998)', 'Princess Bride, The (1987)',
       'Schindler's List (1993)', 'L.A. Confidential (1997)',
       'Groundhog Day (1993)', 'E.T. the Extra-Terrestrial (1982)',
       'Star Wars: Episode I - The Phantom Menace (1999)',
       'Being John Malkovich (1999)', 'Shawshank Redemption, The (1994)',
       'Godfather, The (1972)', 'Forrest Gump (1994)', 'Ghostbusters (1984)',
       'Pulp Fiction (1994)', 'Terminator, The (1984)', 'Toy Story (1995)',
       'Alien (1979)', 'Total Recall (1990)', 'Fugitive, The (1993)',
       'Gladiator (2000)', 'Aliens (1986)', 'Blade Runner (1982)',
       'Who Framed Roger Rabbit? (1988)', 'Stand by Me (1986)',
       'Usual Suspects, The (1995)', 'Babe (1995)', 'Airplane! (1980)',
       'Independence Day (ID4) (1996)', 'Galaxy Quest (1999)',
       'One Flew Over the Cuckoo's Nest (1975)', 'Wizard of Oz, The (1939)',
       '2001: A Space Odyssey (1968)', 'Abyss, The (1989)',
       'Bug's Life, A (1998)', 'Jaws (1975)', 'Godfather: Part II, The (1974)',
       'Casablanca (1942)', 'Die Hard (1988)', 'GoodFellas (1990)',
       'Hunt for Red October, The (1990)', 'Speed (1994)',
       'Indiana Jones and the Last Crusade (1989)', 'Lethal Weapon (1987)',
       'Monty Python and the Holy Grail (1974)', 'Toy Story 2 (1999)',
       'When Harry Met Sally... (1989)', 'Good Will Hunting (1997)',
       'Titanic (1997)', 'Breakfast Club, The (1985)',
       'Mission: Impossible (1996)', 'Election (1999)', 'X-Men (2000)',
       'Twelve Monkeys (1995)', 'Beetlejuice (1988)', 'Big (1988)',
       'Ferris Bueller's Day Off (1986)', 'Edward Scissorhands (1990)',
       'Close Encounters of the Third Kind (1977)', 'Fight Club (1999)',
       'Dances with Wolves (1990)', 'Star Trek: The Wrath of Khan (1982)',
       'Raising Arizona (1987)',
       'Austin Powers: The Spy Who Shagged Me (1999)', 'Batman (1989)',
       'As Good As It Gets (1997)', 'Face/Off (1997)',
       'Butch Cassidy and the Sundance Kid (1969)', 'Thelma & Louise (1991)',
       'Clerks (1994)', 'True Lies (1994)', 'American Pie (1999)',
       'Contact (1997)', 'Amadeus (1984)', 'Fifth Element, The (1997)',
       'High Fidelity (2000)', 'There's Something About Mary (1998)',
       'Dr. Strangelove or: How I Learned to Stop Worrying and Love the Bomb (1963)',
       'Arachnophobia (1990)', 'Clueless (1995)', 'Get Shorty (1995)',
       'Jerry Maguire (1996)', 'Christmas Story, A (1983)', 'Aladdin (1992)',
       'Romancing the Stone (1984)', 'Blues Brothers, The (1980)',
       'Rock, The (1996)'],
      dtype='object', name='Title')

獲取在列表內的電影:

#平均分的資料 看頭100個評分的資料是否在裡面
print(movie_rating_mean.index.isin(top_movie_title2).sum())
flag = movie_rating_mean.index.isin(top_movie_title2)
display(flag.shape,flag)
# 熱門電影平均分
movie_rating_top_mean = movie_rating_mean[flag]
movie_rating_top_mean

顯示:

對列表內的電影根據評分排名排序:

movie_rating_top_mean.sort_values(by = 'Rating',ascending=False)
  • 1

顯示:

由上處資料處理和分析的過程中可以看到,在資料處理過程中,合併透視分組排序這四大類操作是最經常用的,需要熟練掌握。