---
title: 南大_大數據應用(2021/02/01-2021/06/30)
tags: 大數據分析,Hadoop
description: 本門課的重點在輔導學生了解大數據的歷史由來及發展現狀,分享大數據零售行業、電信行業、互聯網行業相關企業的真實案例。
lang: zh
---
# 大數據應用
###### tags: 大數據分析,bigdata,opendata,hadoop
## 重要課程規定
### 評分方式
1. 出席:10%
2. 考試:20%
3. 平時成績(出席、課堂表現、作業、報告):70%
4. [額外全國競賽加分](https://tcat2021.twisc.ncku.edu.tw/):<font color="red">依課程說明</font>
## 課程大綱
本門課將以資安議題為出發角度,教導學生如何利用現有的網路相關log發掘出潛在的資安問題,並由淺入深教導學生如何看懂相關資料,並做出對應的分析結果。
## 相關使用軟體
1. Excel
2. Apache Hadoop Pig、Hive
3. Wireshark 封包分析
## 課程重要行程
1. 期中考:110年04月15日。
2. 全國競賽初賽(課堂時間比):110年04月29日。
3. <font color="RED">110年05月06日停課乙次</font> -> 補課日期為110年05月13日第10(A)節、第11(B)節。
4. T貓盃資安基礎競賽-數據分析組-全國競賽決賽(成大決賽):110年05月13日。
5. 期末報告:110月06月24日。 <font color="red">(暫定)</font>
## 課程相關線上教材
1. 電子書:[大數據(Big Data)分析與應用:使用Hadoop與Spark](https://nutn.ebook.hyread.com.tw/bookDetail.jsp?id=160971)
2. 線上影音教學: [Hadoop 線上課程](https://www.youtube.com/watch?v=I4esbC7ipbk&list=PLUuQL_ogRVuixcTdE9Q0XhvWz6l3p9xbC)
## 初探大數據課程
1. 使用資料集 ([會員註冊資料](https://drive.google.com/file/d/1QOMHY3e0uXyhD-8W-7RCiTcvhB58R4u2/view?usp=sharing)、[會員點播紀錄](https://drive.google.com/file/d/1XgkzUUAVXFdJHsEJ9K-pidzqKfY_IS8q/view?usp=sharing))
userprofile.tsv (會員註冊資料)
| 欄位名稱 | 描述 | 型態 |
| -------- | -------- | -------- |
| userid | 使用者 ID | chararray |
| gender | 性別 | chararray |
| age | 年齡 | int |
| country | 國家 | chararray |
| registered | 註冊日期 | chararray |
userdemand.tsv (會員點播紀錄)
| 欄位名稱 | 描述 | 型態 |
| -------- | -------- | -------- |
| userid | 使用者 ID | chararray |
| time | 點聽時間 | chararray |
| artname | 歌手名稱 | chararray |
| traname | 歌曲名稱 | chararray |
### 2021/03/04 課堂練習題目 (基礎-Excel)
#### 練習1 男性與女性的會員數分別是多少
:::spoiler 參考答案
m 182
f 137
:::
#### 練習2 來自於加拿大(Canada)的男性會員人數
::: spoiler 參考答案
29
:::
#### 練習3 來自於加拿大(Canada)或男性會員人數
:::info
可先找出男性會員人數與加拿大會員人數再減去交集的部分即可找出答案
:::
:::info
可使用 OR 函數進行資料前處理,處理完再進行塞選
:::
::: spoiler 參考答案
213
:::
#### 練習4 年齡介於20~30歲的會員人數
::: spoiler 參考答案
138
:::
#### 練習5 請查詢高於平均會員年齡的會員人數
::: spoiler 參考答案
117
:::
#### 練習6 請查詢年齡最多的前名五分別是幾歲與人數為何
::: spoiler 參考答案
21 35
22 34
24 20
23 20
19 19
:::
### 2021/03/11 課堂練習題目 (基礎-Excel)
#### 練習1 請根據資料集查詢出所有會員資料表中,年輕族群(<30歲)的會員人數分別來自於那些國家(顯示前五名)
國家(顯示前五名)
::: spoiler 參考答案
Canada 47
Germany 23
China 21
Poland 19
United States 11
:::
#### 練習2 請根據資料集查詢出所有會員資料表中,那些國家的男性會員註冊人數是最多的,請顯示國家名稱與註冊人數
::: spoiler 參考答案
Canada 29
:::
#### 練習3 請根據資料集查詢出所有會員資料表中,年長族群(>40)的會員人數分別來自於那些國家(顯示前五名)
::: spoiler 參考答案
Taiwan 6
China 3
Germany 2
Canada 1
Switzerland 1
:::
:::info
在塞選資料時,可以適時的使用資料前處理來過濾出適當的資料,在進行後續的運算。
:::
#### 練習4 請根據資料集查詢出所有會員資料表中,查詢出每個國家年齡介於(30~50)歲的男性會員人數(顯示前五名)
:::info
在使用IF函數時,可搭配AND、OR函數來使用增加查詢效率
:::
::: spoiler 參考答案
Germany 11
Canada 9
Taiwan 4
Norway 2
China 2
:::
#### 練習5 請查詢每個國家的男性與女性會員人數,並顯示出男性會員人數前五名的國家
::: spoiler
Canada 31 29 60
Germany 9 26 35
China 18 16 34
Taiwan 9 11 20
Turkey 4 10 14
:::
#### 練習6 請查詢每個國家的男性與女性會員比例,並顯示出男性會員比例最高的前五名國家,如果名次相同請依照國家名稱由A-Z排序(僅顯示前五筆資料)
::: spoiler
Argentina
British Indian Ocean Territory
Chile
Estonia
France
:::
### 2021/03/18 隨堂測驗 (基礎-Excel)
#### 題目1 台灣與中國的會員人數為多少人?
#### 題目2 台灣的男性會員為多少人?
#### 題目3 年紀最長者來自於哪個國家?
#### 題目4 男性會員中年紀最輕來自於哪個國家?
#### 題目5 哪個國家的壯年族群(>=25 <=40)的人數最多?
#### 題目6 哪個國家的平均年齡最輕?
#### 題目7 找出在所有男性會員中比例最高的國家,並顯示國家名稱與比例
#### 題目8 找出來自於女性會員或來自於德國的人數
### 2021/03/25 課堂練習題目 (基礎-Excel)
#### 練習1 在點播紀錄中,哪一個歌手的點播次數最多,請顯示歌手名稱與點播次數
::: spoiler 參考答案
Radiohead 997
:::
#### 練習2 在點播紀錄中,哪一首歌曲的點播次數最多
::: spoiler 參考答案
Intro 169
:::
#### 練習3 哪一首歌曲擁有最多的歌手翻唱,分別為多少次
::: spoiler 參考答案
Intro 103
:::
#### 練習4 哪一首歌手擁有最多的翻唱歌曲,分別為多少次
::: spoiler 參考答案
The Beatles 213
:::
#### 練習5 點播次數最多的會員來自於哪個國家
::: spoiler 參考答案
Canada 3459
:::
#### 練習6 哪個國家的總點播次數是最多的,顯示國家名稱與次數
::: spoiler 參考答案
Canada 37110
:::
### 2021/04/01 課堂練習題目 (Wireshark 封包解析)
#### 課程檔案下載連結
[Wireshark 檔案下載](https://www.wireshark.org/download.html)
[分析檔案位置](https://drive.google.com/drive/folders/1PEOVCOUbPJ-m4Z6jGQ0uRJRPslet_1o1?usp=sharing)
#### 塞選器的使用
1. 擷取篩選器 (Capture filter)
2. 顯示篩選器 (Display filter)
#### 擷取篩選器常見語法
Type 識別ID名稱或代號 host, port
Dir 來源或目的地 src , dst
Proto 限定協定 ip, tcp, udp, http, ftp
#### 顯示塞選器常見語法
1. 過濾指定IP
ip.addr == 172.217.24.3
ip.src == 172.217.24.3
ip.dst == 172.217.24.3
2. 查詢指定協定
http,http2,tls,arp,ftp,icmp ....
3. 常見運算子
(==) 等於
(!=) 不等於
(>) 大於
(<) 小於
(>=) 大於等於
(<=) 小於等於
Contains 包含
Matches 正則表示查詢
In 在某個集合中
#### 練習1: 查詢IP 來自於 23.41.69.177
::: spoiler 參考語法
ip.addr == 23.41.69.177
:::
#### 練習2: 查詢IP 來源是 23.41.69.177
::: spoiler 參考語法
ip.src == 23.41.69.177
:::
#### 練習3: 查詢IP 目的是 23.41.69.177
::: spoiler 參考語法
ip.dst == 23.41.69.177
:::
#### 練習4: 查詢IP 來自於 140.133.2.17 且 屬於ICMP的封包
:::spoiler 參考語法
ip.src == 140.133.2.17 and icmp
:::
#### 練習5: 查詢封包大小不足50的封包有哪些
:::spoiler 參考語法
frame.len < 50
:::
#### 練習6: 只顯示tcp協定且port為80的封包
:::spoiler 參考語法
tcp.port == 80
:::
#### 練習7: 查詢HTTP協定並使用POST的方法的封包有哪些
:::spoiler 參考語法
http.request.method == "POST"
:::
### 2021/04/08 課堂練習題目 (Wireshark 封包解析)
#### 練習1:請查詢封包紀錄中,有多少封包是HTTP封包
#### 練習2:請查詢封包紀錄中,有多少JPEG圖片是透過HTTP來進行傳輸的
#### 練習3:請查詢封包紀錄中,HTTP的Request跟Response封包各為多少
#### 練習4:請查詢封包紀錄中,有多少HTTP的封包狀態代碼是302的
#### 練習5:請查詢封包紀錄中,有多少HTTP的封包的請求是使用GET傳輸的
#### 練習6:請查詢封包紀錄中,傳送流量最高的IP是哪一個
### 2021/04/15 期中考
#### 考試相關資訊
1. [考試相關檔案下載](https://drive.google.com/drive/folders/1c-lG2QO6i2wdpRlt3dVsNJ37eJV9HDdo?usp=sharing)
2. [線上作答網址](https://docs.google.com/forms/d/e/1FAIpQLSdz2-K7g9LdmW-F1bLU5Bf-ipJiGgrf2j2SE7P5IiZMWwZavQ/viewform)
3. 考試開放時間:110/04/15 14:30 - 110/04/15 15:40
#### 考試題目
1. 請查詢出在9~12月份註冊的會員人數
:::spoiler
101
:::
2. 請查詢註冊人數介於20~30的國家有哪些,請顯示國家名稱與會員人數
:::spoiler
Taiwan 20
:::
3. 在點播紀錄中,點播次數排名第三名的歌手為哪位歌手,請顯示歌手名稱與點播次數
:::spoiler
Chemistry 780
:::
4. 在點播紀錄中,點播次數排名第三名的歌曲為哪首歌,請顯示歌曲名稱與點播次數
:::spoiler
Say You Will 74
Love Lockdown 74
:::
5. 請顯示點播次數排名前五名的國家與點播次數
:::spoiler
Canada 37110
Germany 14558
Turkey 10707
Poland 10664
United States 9255
:::
6. 請根據封包紀錄檔所錄製的封包,查詢出來源端或目的端的IP為 52.117.224.148的封包數量 (Packets)有多少個
:::spoiler
54
:::
7. 請根據封包紀錄檔所錄製的封包,查詢出icmp的封包數量(Packets)有多少個,並查詢出與哪個IP進行icmp通訊
:::spoiler
17 192.192.45.119
:::
8. 我們側錄到使用者曾經上過eyny的論壇並搜尋一組關鍵字,請幫我根據側錄的封包找出這組關鍵字
:::spoiler
天竺鼠車車
:::
9. 我們側錄到使用者曾經上過eyny的論壇並有登入紀錄,請幫我根據側錄的封包找出該名使用者的帳號與密碼
:::spoiler
帳號:frank
密碼:15750705145A
:::
10. 請根據側錄的封包查詢出使用HTTP傳輸協定下載的圖片封包數量(Packets)與大小(Bytes)
:::spoiler
Packets:37 Bytes:508501
:::
### 2021/05/27 C# 數據分析資料
#### 練習一:判斷奇數偶數
```csharp=
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace D20210527
{
class Program
{
static void Main(string[] args)
{
Console.Write("請輸入一個整數:");
String temp = Console.ReadLine();
Console.Write(temp);
int Number = Int32.Parse(temp);
if (Number % 2 == 0)
{
Console.WriteLine("是一個偶數");
}
else
{
Console.WriteLine("是一個奇數");
}
Console.ReadKey();
}
}
}
```
#### 練習二:判斷某個網頁上的數字是奇數還是偶數
```csharp=
static async void Task()
{
//建立一個HttpClient的物件(類似瀏覽器)
HttpClient client = new HttpClient();
//命令瀏覽器發出一個請求,取得某個網頁的內容
String webData = await client.GetStringAsync("https://testbed.tcat2021.twisc.ncku.edu.tw:20014/");
//將網站上抓到的結果顯示在Console中
Console.WriteLine(webData);
}
static void Main(string[] args)
{
Task();
Console.ReadKey();
}
```
### 2021/06/03 C# 數據分析資料
#### 練習一:計算網頁上的資料
```csharp=
static async void WebTask()
{
//建立一個HttpClient的物件(類似瀏覽器)
HttpClient client = new HttpClient();
//設定一個遠端連線的網址
String URL = "https://testbed.tcat2021.twisc.ncku.edu.tw:20001/";
//命令瀏覽器發出一個請求,取得某個網頁的內容
String webData = await client.GetStringAsync(URL);
//資料前處理
String[] data = webData.Split(',');
//將文字轉換成浮點數(小數)
double Num1 = Double.Parse(data[0]);
double Num2 = Double.Parse(data[1]);
//將計算後的結果存放到Result的變數中
String result = String.Format("{0} + {1} = {2}", Num1, Num2, Num1 + Num2);
//將查詢到的結果顯示出來
Console.WriteLine(result);
}
```
#### 練習二:讀取多筆資料
```csharp=
//建立一個HttpClient的物件(類似瀏覽器)
HttpClient client = new HttpClient();
//設定一個遠端連線的網址
String URL = "https://testbed.tcat2021.twisc.ncku.edu.tw:20001/";
//命令瀏覽器發出一個請求,取得某個網頁的內容
String webData = await client.GetStringAsync(URL);
//將資料分成多筆資料 (\r\n)
String[] colData = Regex.Split(webData, "\r\n");
//利用迴圈將檔案讀取出來
for (int i = 0; i < colData.Length; i++)
{
Console.WriteLine(String.Format("第{0}筆資料為:{1}",i, colData[i]));
}
```
#### 練習三:從網站上抓取多筆資料並計算結果
```csharp=
static async void WebTask()
{
//建立一個HttpClient的物件(類似瀏覽器)
HttpClient client = new HttpClient();
//設定一個遠端連線的網址
String URL = "https://testbed.tcat2021.twisc.ncku.edu.tw:20001/";
//命令瀏覽器發出一個請求,取得某個網頁的內容
String webData = await client.GetStringAsync(URL);
//將資料分成多筆資料 (\r\n)
String[] colData = Regex.Split(webData, "\r\n");
//利用迴圈將檔案讀取出來
for (int i = 0; i < colData.Length; i++)
{
Console.WriteLine(String.Format("第{0}筆資料為:{1}", i + 1, colData[i]));
//資料前處理
String[] data = colData[i].Split(',');
//將文字轉換成浮點數(小數)
double Num1 = Double.Parse(data[0]);
double Num2 = Double.Parse(data[1]);
//將計算後的結果存放到Result的變數中
String result = String.Format("{0} + {1} = {2}", Num1, Num2, Num1 + Num2);
Console.WriteLine(result);
}
}
```
#### 練習四:查詢台中車禍相關資料
```csharp=
static async void WebTask()
{
//建立一個HttpClient的物件(類似瀏覽器)
HttpClient client = new HttpClient();
//設定一個遠端連線的網址
String URL = "https://datacenter.taichung.gov.tw/swagger/OpenData/18fcbc2f-f843-46e1-b08c-87d86f4b6c0f";
//命令瀏覽器發出一個請求,取得某個網頁的內容
String webData = await client.GetStringAsync(URL);
//將資料分成多筆資料 (\r\n)
String[] colData = Regex.Split(webData, "\r\n");
//利用迴圈將檔案讀取出來
for (int i = 1; i < 10; i++)
{
//資料前處理
String[] data = colData[i].Split(',');
//顯示輸出的內容格式
String result = String.Format("車禍發生時間:{0}/{1}/{2} {3}:{4} 發生地點:{5} {6}",
data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
//將結果顯示在Console 上
Console.WriteLine(result);
}
}
```
### 2021/06/10 C# 數據分析資料
#### 練習一:查詢每天車禍總資料筆數
```csharp=
static async void WebTask()
{
//建立一個HttpClient的物件(類似瀏覽器)
HttpClient client = new HttpClient();
//設定一個遠端連線的網址
String URL = "https://datacenter.taichung.gov.tw/swagger/OpenData/18fcbc2f-f843-46e1-b08c-87d86f4b6c0f";
//命令瀏覽器發出一個請求,取得某個網頁的內容
String webData = await client.GetStringAsync(URL);
//將資料分成多筆資料 (\r\n)
String[] colData = Regex.Split(webData, "\r\n");
//宣告一個陣列用來記錄每天發生車禍的筆數
int[] dayCount = new int[32];
//利用迴圈將檔案讀取出來
for (int i = 1; i < colData.Length; i++)
{
//資料前處理
String[] data = colData[i].Split(',');
if (data.Length == 50)
{
//顯示輸出的內容格式
String result = String.Format("車禍發生時間:{0}/{1}/{2} {3}:{4} 發生地點:{5} {6}",
data[0], data[1], data[2], data[3], data[4], data[5], data[6]);
int nowDay = int.Parse(data[2]);
dayCount[nowDay] = dayCount[nowDay] + 1;
//將結果顯示在Console 上
Console.WriteLine(result);
}
}
for (int i = 1; i < dayCount.Length; i++)
{
Console.WriteLine("2021/03/{0} 一共發生了 {1} 筆車禍", i, dayCount[i]);
}
}
```
#### 練習二:查詢每天的車禍筆數 其中包含受傷人數與死亡人數
```csharp=
static async void WebTask()
{
//建立一個HttpClient的物件(類似瀏覽器)
HttpClient client = new HttpClient();
//設定一個遠端連線的網址
String URL = "https://datacenter.taichung.gov.tw/swagger/OpenData/18fcbc2f-f843-46e1-b08c-87d86f4b6c0f";
//命令瀏覽器發出一個請求,取得某個網頁的內容
String webData = await client.GetStringAsync(URL);
//將資料分成多筆資料 (\r\n)
String[] colData = Regex.Split(webData, "\r\n");
//宣告一個陣列用來記錄每天發生車禍的筆數,死亡人數與受傷人數
int[] dayCount = new int[32];
int[] deatCount = new int[32];
int[] injuredCount = new int[32];
//利用迴圈將檔案讀取出來
for (int i = 1; i < colData.Length; i++)
{
//資料前處理
String[] data = colData[i].Split(',');
if (data.Length == 50)
{
//顯示輸出的內容格式
String result = String.Format("車禍發生時間:{0}/{1}/{2} {3}:{4} 發生地點:{5} {6} 死亡人數:{7} 受傷人數:{8}",
data[0], data[1], data[2], data[3], data[4], data[5], data[6] , data[7] , data[8]);
//讀取該筆資料為第n天的資料
int nowDay = int.Parse(data[2]);
//讀取第N天的資料 並且把第N天的資料數量+1
dayCount[nowDay] = dayCount[nowDay] + 1;
//加總死亡人數
if (data[7] != "")
{
int deatNum = int.Parse(data[7]);
deatCount[nowDay] = deatCount[nowDay] + deatNum;
}
//加總受傷人數
if (data[8] != "")
{
int injureNum = int.Parse(data[8]);
injuredCount[nowDay] = injuredCount[nowDay] + injureNum;
}
//將結果顯示在Console 上
//Console.WriteLine(result);
}
}
//利用迴圈將每天車禍發生的筆數顯示出來
for (int i = 1; i < dayCount.Length; i++)
{
Console.WriteLine("2021/03/{0} 一共發生了 {1} 筆車禍 其中受傷人數為{2}人 死亡人數為{3}",
i,
dayCount[i] ,
injuredCount[i] ,
deatCount[i]);
}
}
```
## 2021/06/17 期末報告範例
```csharp=
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace D20210603
{
class Program
{
static async void WebTask()
{
//建立一個HttpClient的物件(類似瀏覽器)
HttpClient client = new HttpClient();
//設定一個遠端連線的網址
String URL = "https://datacenter.taichung.gov.tw/swagger/OpenData/18fcbc2f-f843-46e1-b08c-87d86f4b6c0f";
//命令瀏覽器發出一個請求,取得某個網頁的內容
String webData = await client.GetStringAsync(URL);
//將資料分成多筆資料 (\r\n)
String[] colData = Regex.Split(webData, "\r\n");
//開始資料的分析
//記錄每天發生的車禍次數,死亡人數與受傷人數
int[] dayCount = new int[32]; //儲存每天的車禍次數
int[] deathCount = new int[32]; //儲存每天的死亡人數
int[] injuredCount = new int[32]; //儲存每天的受傷人數
//記錄每個區域發生的車禍次數,死亡人數與受傷人數
Dictionary<String, int> areaCount = new Dictionary<String, int>();
Dictionary<String, int> areaDeath = new Dictionary<String, int>();
Dictionary<String, int> areaInjured = new Dictionary<String, int>();
Console.WriteLine("原始資料");
//利用迴圈將檔案讀取出來
for (int i = 1; i < colData.Length; i++)
{
//資料前處理
String[] data = colData[i].Split(',');
if (data.Length == 50)
{
//顯示輸出的內容格式
String result = String.Format("車禍發生時間:{0}/{1}/{2} {3}:{4} 發生地點:{5} {6} 死亡人數:{7} 受傷人數:{8}",
data[0], data[1], data[2], data[3], data[4], data[5], data[6] , data[7] , data[8]);
Console.WriteLine(result);
//開始處理每天的資料
int nowDay = int.Parse(data[2]);
//記錄每天發生的車禍次數
dayCount[nowDay] = dayCount[nowDay] + 1;
//加總死亡人數(每天)
if (data[7] != "")
{
int deatNum = int.Parse(data[7]);
deathCount[nowDay] = deathCount[nowDay] + deatNum;
}
//加總受傷人數(每天)
if (data[8] != "")
{
int injureNum = int.Parse(data[8]);
injuredCount[nowDay] = injuredCount[nowDay] + injureNum;
}
//記錄每個區域的車禍次數
String area = data[6];
if (!areaCount.ContainsKey(area))
{
areaCount.Add(area,0);
}
areaCount[area] = areaCount[area] + 1;
//記錄每個區域的死亡人數
if (!areaDeath.ContainsKey(area))
{
areaDeath.Add(area, 0);
}
//加總死亡人數(每天)
if (data[7] != "")
{
int deatNum = int.Parse(data[7]);
areaDeath[area] = areaDeath[area] + deatNum;
}
//記錄每個區域的受傷人數
if (!areaInjured.ContainsKey(area))
{
areaInjured.Add(area, 0);
}
//加總受傷人數(每天)
if (data[8] != "")
{
int injuredNum = int.Parse(data[8]);
areaInjured[area] = areaInjured[area] + injuredNum;
}
}
}
// Console.Write("請按任意鍵繼續查看");
// Console.ReadKey();
Console.WriteLine("每天發生的車禍筆數 受傷人數 與 死亡人數");
//利用迴圈將每天車禍發生的筆數顯示出來
for (int i = 1; i < dayCount.Length; i++)
{
Console.WriteLine("2021/03/{0} 一共發生了 {1} 筆車禍 其中受傷人數為{2}人 死亡人數為{3}",
i,
dayCount[i] ,
injuredCount[i] ,
deathCount[i]);
}
//Console.Write("請按任意鍵繼續查看");
//Console.ReadKey();
Console.WriteLine("每個區域的車禍筆數 受傷人數 與 死亡人數");
//利用迴圈將每天車禍發生的筆數顯示出來
foreach(var temp in areaCount)
{
Console.WriteLine("{0} 一共發生了 {1} 筆車禍 其中受傷人數為{2}人 死亡人數為{3}",
temp.Key,
areaCount[temp.Key],
areaInjured[temp.Key],
areaDeath[temp.Key]);
}
}
static void Main(string[] args)
{
WebTask();
Console.ReadKey();
}
}
}
```