1.資料轉換
1.套用向量化計算(例子依然使用我們採集的房天下的資料)
- 計算新價格
df['總價'] * 1000
複製程式碼
- 使用 Numpy計算新的價格
np.sqrt() 代表開根號
import numpy as np
np.sqrt(df['總價'])
複製程式碼
- 合併兩字串
df['朝向'] + df['戶型']
複製程式碼
- 將新計算的均價存入DataFrame
df['均價'] = df['總價'] * 1000 / df['建築面積']
複製程式碼
2.定義函式進行套用
- map:將函式套用到Series 上的每個元素
eg. 移除物業費中的元
def removeDollar(e):
return e.split('元')[0]
df['物業費'].map(removeDollar)
複製程式碼
eg. 使用匿名函式
df['物業費'].map(lambda e: e.split('元')[0])
複製程式碼
- Apply:將函式套用到DataFrame 上的行與列
eg:
df = pandas.DataFrame([
[60,70,50],\
[80,79,68],\
[63,66,82]], columns = ['First', 'Second', 'Third']
)
複製程式碼
# 以列進行計算
df.apply(lambda e: e.max() - e.min())
複製程式碼
# 以行進行計算
df.apply(lambda e: e.max() - e.min(), axis = 1)
複製程式碼
- ApplyMap:將函式套用到DataFrame上的每個元素(elementwise) 將所有暫無資料的元素替代成缺失值(NaN)
import numpy as np
df.applymap(lambda e :np.nan if e == '暫無資料' else e)
複製程式碼
2.處理時間格式資料
- 列印出現在的時間
from datetime import datetime
current_time = datetime.now()
複製程式碼
- 將時間轉換成字串
current_time.strftime('%Y-%m-%d')
複製程式碼
- 將字串轉化為時間
datetime.strptime('2017-04-21', '%Y-%m-%d')
複製程式碼
- 時間回溯
from datetime import timedelta
current_time - timedelta(days = 1)
複製程式碼
- 往前回溯10天(這裡的適用場景是想取得過去10天的資訊)
for i in range(1, 10):
dt = currnet_time - timedelta(days = i)
print(dt.strftime('%Y-%m-%d'))
複製程式碼
注意:這裡的時間轉換後的格式可以根據需要設定,eg:dt.strftime('%Y/%m/%d')
3.轉換UNIX時間,即從1970年1月1日到現在過了多少秒
- 將datetime轉換為UNIX timestamp
from time import mktime
mktime(current_time.timetuple())
複製程式碼
- 將UNIX timestamp 轉換為datetime
datetime.fromtimestamp(1492859823)
複製程式碼
4.在pandas轉換時間
- 轉換前
import pandas
df = pandas.read_excel('data/house_sample.xlsx')
df['張貼日期'] = pandas.to_datetime(df['張貼日期'], format = '西元%Y年%m月%d日')
複製程式碼
- 轉換後
3.重塑資料
1.虛擬變數(Dummy Variable)
百度百科:
虛擬變數 ( Dummy Variables) 又稱虛設變數、名義變數或啞變數,用以反映質的屬性的一個人工變數,是量化了的自變數,通常取值為0或1。引入啞變數可使線形迴歸模型變得更復雜,但對問題描述更簡明,一個方程能達到兩個方程的作用,而且接近現實。
eg:如下表中的朝向就可以建立一個虛擬變數
- 建立虛擬變數
pandas.get_dummies(df['朝向'])
複製程式碼
- 合併虛擬變數與原DataFrame
df = pandas.concat([df, pandas.get_dummies(df['朝向'])], axis = 1)
複製程式碼
- 捨棄原有欄位
df.drop('朝向', axis = 1)
複製程式碼
2.建立透視表(pivot_table)
df2 = df.pivot_table(index = '張貼日期', columns = '產權性質', values = '總價', aggfunc = sum, fill_value = 0)
# fill_value = 0 指代的是把NaN替換成0
df2.head()
複製程式碼
df3 = df.pivot_table(index = '產權性質', columns = '張貼日期', values = '總價', aggfunc = sum)
df3.head()
複製程式碼
另外,兩者進行轉換的話也可以直接通過df2.T
做轉換。
##3.長寬表格的轉換(stack & unstack)
- 建立多索引的透視表
df_multi_idx = df.pivot_table(index=['樓層', '裝修'],columns='張貼日期', values='總價', aggfunc=sum)
複製程式碼
- 轉換為寬表格
df_wide = df_multi_idx.unstack()
df_wide.head()
複製程式碼
- 轉換為長表格
df_long = df_wide.stack()
df_long.head()
複製程式碼
4.學習正規表示式
1.正規表示式概述
正規表示式,又稱正規表示式、正規表示法、正規表示式、規則表示式、常規表示法(英語:Regular Expression,在程式碼中常簡寫為regex、regexp或RE),是電腦科學的一個概念。正規表示式使用單個字串來描述、匹配一系列匹配某個句法規則的字串。在很多文字編輯器裡,正規表示式通常被用來檢索、替換那些匹配某個模式的文字。
Regular Expression的“Regular”一般被譯為“正則”、“正規”、“常規”。此處的“Regular”即是“規則”、“規律”的意思,Regular Expression即“描述某種規則的表示式”之意。
Python通過re模組提供對正規表示式的支援。使用re的一般步驟是先使用re.compile()函式,將正規表示式的字串形式編譯為Pattern例項,然後使用Pattern例項處理文字並獲得匹配結果(一個Match例項),最後使用Match例項獲得資訊,進行其他的操作。
1.正規表示式(Regular Expression):查詢和匹配字串的規則
2.正規表示式表示資料
普通字元: 後設資料,可以用於匹配指定的字元
r = “a”:用於在目標字串中匹配小寫字母a元字元
r = “.”:用於匹配任意一個字元
r = “\”:轉移字元~用於將一個普通的字元,轉義成一個有意義的字元
r = “\d”:表示一個0~9之間的整數
r = “\D”:表示一個非數字字元
r = “\w”:表示任意一個0~9或者字母或者下劃線的字元
r = “\W”:表示任意一個特殊字元
r = “\s”:表示匹配一個空白字元
r = “\S”:表示匹配一個非空白字元
r = “^”:匹配字串的開頭位置
r = “$”:匹配字串的結束位置
r = “\d*”:表示前面匹配的字元出現了0次或者多次
r = “\d?”:表示前面匹配的字元出現了0次或者1次
r =”\d+”:表示前面匹配的字元出現了1次或者多次
#範圍匹配
分組匹配方式:將多個匹配字元當成一個完整的匹配公式
(abc):用於在目標字串中查詢abc同時出現的地方
選擇匹配方式:將指定的多個字元,選擇其中一個進行匹配
[abc]:用於在目標字串中,查詢a或者b或者c出現的地方
[0-9]:用於匹配一個0~9之間的數字->等價於\d
[a-z]:用於匹配一個a-z之間的字母
[A-Z]:用於匹配一個A-Z之間的字母
[a-zA-Z]:用於匹配一個字母【大小寫均可】
[a-zA-Z0-9_]:用於匹配一個非特殊字元,等價於\w
#範圍匹配
\d{m, n}:匹配到的字元出現了至少m次,最多n次
\d{,20}:匹配一個數字最多出現20次
\d{8,}:匹配一個數字,最少出現8次
\d{8,16}:匹配一個數字,最少出現8次,最多出現16次
#正規表示式在python中的使用
正規表示式,在python中,主要用到了一個re模組
compile():編譯正規表示式
pattern = re.compile(“^\d{2,}$”)
pattern = r‘^\d{2,}$’
pattern.match(str,begin,end):從指定的字串str第一個字元查詢匹配的字元
pattern.search(str, begin, end):從指定的字串中直接進行查詢,查詢到的第一個結果作為匹配結果
pattern.findall(str):從指定的字串中,查詢符合匹配規則的字元,將所有符合的字元存放在一個列表中
pattern.finditer(str):從指定的字串中,查詢符合匹配規則的字元儲存在一個可以迭代的物件中
pattern.sub():替換
pattern.split():拆分
複製程式碼
eg:
import re
email = 'zhiji@github.com'
m = re.match('(\w+)@([a-z\.]+)', email)
or
m = re.match('(\w+)@(.+)', email)
>>>m.group(1)
zhiji
>>>m.group(2)
github.com
>>>m.groups()
('zhiji', 'github.com')
複製程式碼
2.在DataFrame上使用正規表示式
- 從戶型用正規表示式抽取室、廳、廚、衛欄位
df[['室', '廳', '廚', '衛']] = df['戶型'].str.extract('(\d+)室(\d+)廳(\d+)廚(\d+)衛', expand=False)
複製程式碼
之前寫過詳細的正規表示式的文章,傳送門在這裡正規表示式。
5.例項處理
我們通過對新浪微博新聞資料的採集和處理作為案例
import requests
import pandas
import re
from bs4 import BeautifulSoup
def get_article(url):
res1 = requests.get(url)
res1.encoding = 'utf-8'
soup1 = BeautifulSoup(res1.text, 'html.parser')
dic = {}
dic['title'] = soup1.select('.page-header #artibodyTitle')[0].text
dic['content'] = ''.join([ele.text for ele in soup1.select('.article_16 p')])
dic['source'] = soup1.select('#navtimeSource')[0].text
dic['keyword'] = soup1.select('.article-info .article-keywords')[0].text
return dic
def get_all_news():
res = requests.get('http://news.sina.com.cn/china/')
res.encoding = 'utf-8'
soup = BeautifulSoup(res.text, 'html.parser')
newsary = []
for link in soup.select('.news-item'):
if len(link.select('h2 a')) > 0:
newsary.append(get_article(link.select('h2 a')[0]['href']))
df = pandas.DataFrame(newsary)
# 進行資料清理
df['keyword'] = df['keyword'].map(lambda e: e.split(':')[1].split())
# df['source'] = df['source'].map(lambda e: e.split())
df[['datetime', 'from']] = df['source'].str.extract('(\d+年\d+月\d+日\d+:\d+)[\t|\n]+?(\w+)', expand=False)
print(df[['datetime', 'from']])
# 因為df['datetime']是object格式,為了後期的取值,例:取年df['datetime'].map(lambda e : e.year) 我們需要把格式轉換為時間格式
df['datetime'] = pandas.to_datetime(df['datetime'], format = '%Y年%m月%d日%H:%M')
del df['source']
# 對即將儲存的格式進行調整
df = df[['from', 'title', 'content', 'keyword', 'datetime']]
# 將整理好的資料儲存Excel
df.to_excel('news.xlsx')
if __name__ == '__main__':
get_all_news()
複製程式碼