pythonmedian
Ⅰ 如何用python做輿情時間序列可視化
如何批量處理評論信息情感分析,並且在時間軸上可視化呈現?輿情分析並不難,讓我們用Python來實現它吧。
痛點
你是一家連鎖火鍋店的區域經理,很注重顧客對餐廳的評價。從前,你苦惱的是顧客不愛寫評價。最近因為餐廳火了,分店越來越多,寫評論的顧客也多了起來,於是你新的痛苦來了——評論太多了,讀不過來。
從我這兒,你了解到了情感分析這個好用的自動化工具,一下子覺得見到了曙光。
你從某知名點評網站上,找到了自己一家分店的頁面,讓助手把上面的評論和發布時間數據弄下來。因為助手不會用爬蟲,所以只能把評論從網頁上一條條復制粘貼到Excel里。下班的時候,才弄下來27條。(注意這里我們使用的是真實評論數據。為了避免對被評論商家造成困擾,統一將該餐廳的名稱替換為「A餐廳」。特此說明。)
好在你只是想做個試驗而已,將就了吧。你用我之前介紹的中文信息情感分析工具,依次得出了每一條評論的情感數值。剛開始做出結果的時候,你很興奮,覺得自己找到了輿情分析的終極利器。
可是美好的時光總是短暫的。很快你就發現,如果每一條評論都分別運行一次程序,用機器來做分析,還真是不如自己挨條去讀省事兒。
怎麼辦呢?
序列
辦法自然是有的。我們可以利用《貸還是不貸:如何用Python和機器學習幫你決策?》一文介紹過的數據框,一次性處理多個數據,提升效率。
但是這還不夠,我們還可以把情感分析的結果在時間序列上可視化出來。這樣你一眼就可以看見趨勢——近一段時間里,大家是對餐廳究竟是更滿意了,還是越來越不滿意呢?
我們人類最擅長處理的,就是圖像。因為漫長的進化史逼迫我們不斷提升對圖像快速准確的處理能力,否則就會被環境淘汰掉。因此才會有「一幅圖勝過千言萬語」的說法。
准備
首先,你需要安裝Anaconda套裝。詳細的流程步驟請參考《 如何用Python做詞雲 》一文。
助手好不容易做好的Excel文件restaurant-comments.xlsx,請從這里下載。
用Excel打開,如果一切正常,請將該文件移動到咱們的工作目錄demo下。
因為本例中我們需要對中文評論作分析,因此使用的軟體包為SnowNLP。情感分析的基本應用方法,請參考《如何用Python做情感分析?》。
到你的系統「終端」(macOS, Linux)或者「命令提示符」(Windows)下,進入我們的工作目錄demo,執行以下命令。
pip install snownlp
pip install ggplot
運行環境配置完畢。
在終端或者命令提示符下鍵入:
jupyter notebook
如果Jupyter Notebook正確運行,下面我們就可以開始編寫代碼了。
代碼
我們在Jupyter Notebook中新建一個Python 2筆記本,起名為time-series。
首先我們引入數據框分析工具Pandas,簡寫成pd以方便調用。
import pandas as pd
接著,讀入Excel數據文件:
df = pd.read_excel("restaurant-comments.xlsx")
我們看看讀入內容是否完整:
df.head()
結果如下:
注意這里的時間列。如果你的Excel文件里的時間格式跟此處一樣,包含了日期和時間,那麼Pandas會非常智能地幫你把它識別為時間格式,接著往下做就可以了。
反之,如果你獲取到的時間只精確到日期,例如"2017-04-20"這樣,那麼Pandas只會把它當做字元串,後面的時間序列分析無法使用字元串數據。解決辦法是在這里加入以下兩行代碼:
from dateutil import parser
df["date"] = df.date.apply(parser.parse)
這樣,你就獲得了正確的時間數據了。
確認數據完整無誤後,我們要進行情感分析了。先用第一行的評論內容做個小實驗。
text = df.comments.iloc[0]
然後我們調用SnowNLP情感分析工具。
from snownlp import SnowNLP
s = SnowNLP(text)
顯示一下SnowNLP的分析結果:
s.sentiments
結果為:
0.6331975099099649
情感分析數值可以正確計算。在此基礎上,我們需要定義函數,以便批量處理所有的評論信息。
def get_sentiment_cn(text):
s = SnowNLP(text) return s.sentiments
然後,我們利用Python裡面強大的apply語句,來一次性處理所有評論,並且將生成的情感數值在數據框裡面單獨存為一列,稱為sentiment。
df["sentiment"] = df.comments.apply(get_sentiment_cn)
我們看看情感分析結果:
df.head()
新的列sentiment已經生成。我們之前介紹過,SnowNLP的結果取值范圍在0到1之間,代表了情感分析結果為正面的可能性。通過觀察前幾條數據,我們發現點評網站上,顧客對這家分店評價總體上還是正面的,而且有的評論是非常積極的。
但是少量數據的觀察,可能造成我們結論的偏頗。我們來把所有的情感分析結果數值做一下平均。使用mean()函數即可。
df.sentiment.mean()
結果為:
0.7114015318571119
結果數值超過0.7,整體上顧客對這家店的態度是正面的。
我們再來看看中位數值,使用的函數為median()。
df.sentiment.median()
結果為:
0.9563139038622388
我們發現了有趣的現象——中位數值不僅比平均值高,而且幾乎接近1(完全正面)。
這就意味著,大部分的評價一邊倒表示非常滿意。但是存在著少部分異常點,顯著拉低了平均值。
下面我們用情感的時間序列可視化功能,直觀查看這些異常點出現在什麼時間,以及它們的數值究竟有多低。
我們需要使用ggplot繪圖工具包。這個工具包原本只在R語言中提供,讓其他數據分析工具的用戶羨慕得流口水。幸好,後來它很快被移植到了Python平台。
我們從ggplot中引入繪圖函數,並且讓Jupyter Notebook可以直接顯示圖像。
%pylab inlinefrom ggplot import *
這里可能會報一些警告信息。沒有關系,不理會就是了。
下面我們繪制圖形。這里你可以輸入下面這一行語句。
ggplot(aes(x="date", y="sentiment"), data=df) + geom_point() + geom_line(color = 'blue') + scale_x_date(labels = date_format("%Y-%m-%d"))
你可以看到ggplot的繪圖語法是多麼簡潔和人性化。只需要告訴Python自己打算用哪個數據框,從中選擇哪列作為橫軸,哪列作為縱軸,先畫點,後連線,並且可以指定連線的顏色。然後,你需要讓X軸上的日期以何種格式顯示出來。所有的參數設定跟自然語言很相似,直觀而且易於理解。
執行後,就可以看到結果圖形了。
在圖中,我們發現許多正面評價情感分析數值極端的高。同時,我們也清晰地發現了那幾個數值極低的點。對應評論的情感分析數值接近於0。這幾條評論,被Python判定為基本上沒有正面情感了。
從時間上看,最近一段時間,幾乎每隔幾天就會出現一次比較嚴重的負面評價。
作為經理,你可能如坐針氈。希望盡快了解發生了什麼事兒。你不用在數據框或者Excel文件裡面一條條翻找情感數值最低的評論。Python數據框Pandas為你提供了非常好的排序功能。假設你希望找到所有評論里情感分析數值最低的那條,可以這樣執行:
df.sort(['sentiment'])[:1]
結果為:
情感分析結果數值幾乎就是0啊!不過這里數據框顯示評論信息不完全。我們需要將評論整體列印出來。
print(df.sort(['sentiment']).iloc[0].comments)
評論完整信息如下:
這次是在情人節當天過去的,以前從來沒在情人節正日子出來過,不是因為沒有男朋友,而是感覺哪哪人都多,所以特意錯開,這次實在是饞A餐廳了,所以趕在正日子也出來了,從下午四點多的時候我看排號就排到一百多了,我從家開車過去得堵的話一個小時,我一看提前兩個小時就在網上先排著號了,差不多我們是六點半到的,到那的時候我看號碼前面還有才三十多號,我想著肯定沒問題了,等一會就能吃上的,沒想到悲劇了,就從我們到那坐到等位區開始,大約是十分二十分一叫號,中途多次我都想走了,哈哈,哎,等到最後早上九點才吃上的,服務員感覺也沒以前清閑時周到了,不過這肯定的,一人負責好幾桌,今天節日這么多人,肯定是很累的,所以大多也都是我自己跑腿,沒讓服務員給弄太多,就蝦滑讓服務員下的,然後環境來說感覺衛生方面是不錯,就是有些太吵了,味道還是一如既往的那個味道,不過A餐廳最人性化的就是看我們等了兩個多小時,上來送了我們一張打折卡,而且當次就可以使用,這點感覺還是挺好的,不愧是A餐廳,就是比一般的要人性化,不過這次就是選錯日子了,以後還是得提前預約,要不就別趕節日去,太火爆了!
通過閱讀,你可以發現這位顧客確實有了一次比較糟糕的體驗——等候的時間太長了,以至於使用了「悲劇」一詞;另外還提及服務不夠周到,以及環境吵鬧等因素。正是這些詞彙的出現,使得分析結果數值非常低。
好在顧客很通情達理,而且對該分店的人性化做法給予了正面的評價。
從這個例子,你可以看出,雖然情感分析可以幫你自動化處理很多內容,然而你不能完全依賴它。
自然語言的分析,不僅要看錶達強烈情感的關鍵詞,也需要考慮到表述方式和上下文等諸多因素。這些內容,是現在自然語言處理領域的研究前沿。我們期待著早日應用到科學家們的研究成果,提升情感分析的准確度。
不過,即便目前的情感分析自動化處理不能達到非常准確,卻依然可以幫助你快速定位到那些可能有問題的異常點(anomalies)。從效率上,比人工處理要高出許多。
你讀完這條評論,長出了一口氣。總結了經驗教訓後,你決定將人性化的服務貫徹到底。你又想到,可以收集用戶等候時長數據,用數據分析為等待就餐的顧客提供更為合理的等待時長預期。這樣就可以避免顧客一直等到很晚了。
祝賀你,經理!在數據智能時代,你已經走在了正確的方向上。
下面,你該認真閱讀下一條負面評論了……
討論
除了情感分析和時間序列可視化,你覺得還可以如何挖掘中文評論信息?除了點評網站之外,你還知道哪些輿情分析的數據來源?歡迎留言分享給大家,我們一起交流討論。
如果你對我的文章感興趣,歡迎點贊,並且微信關注和置頂我的公眾號「玉樹芝蘭」(nkwangshuyi)。
如果你身邊有好友正在做輿情分析的研究工作,也歡迎你把這篇文章轉發給他們,共同學習和提高。
Ⅱ 中位數python代碼
使用python找到一列數的中位數並輸出的代碼示例如下,只有9行代碼:
import random;
N=9;lst=[
random.randint(0,100)
for i in range(N)];
lst.sort();
l=len(lst);
print("sorted:",lst);
print("median:",
sum(lst[((l-1)//2):(l//2+1)])/2);
Ⅲ 如何用python求list的中位數
defmedian(lst):
ifnotlst:
return
lst=sorted(lst)
iflen(lst)%2==1:
returnlst[len(lst)//2]
else:
return(lst[len(lst)//2-1]+lst[len(lst//2])/2.0
Ⅳ 如何計算百分位數與Python / numpy的
1. 你可能會喜歡SciPy的統計軟體包。它有百分函數你之後,許多其他統計好吃的東西。
此票證相信他們不會被整合percentile()到numpy的很快。
2.
順便說一句,有百分函數的純Python,萬一一個不希望依賴於SciPy的。具體函數如下復制:
## {{{ CodeGo.net (r1)
import math
import functools
def percentile(N, percent, key=lambda x:x):
"""
Find the percentile of a list of values.
@parameter N - is a list of values. Note N MUST BE already sorted.
@parameter percent - a float value from 0.0 to 1.0.
@parameter key - optional key function to compute value from each element of N.
@return - the percentile of the values
"""
if not N:
return None
k = (len(N)-1) * percent
f = math.floor(k)
c = math.ceil(k)
if f == c:
return key(N[int(k)])
d0 = key(N[int(f)]) * (c-k)
d1 = key(N[int(c)]) * (k-f)
return d0+d1
# median is 50th percentile.
median = functools.partial(percentile, percent=0.5)
## end of CodeGo.net }}}
3.
檢查scipy.stats模塊:
scipy.stats.scoreatpercentile
4.
import numpy as np
a = [154, 400, 1124, 82, 94, 108]
print np.percentile(a,95) # gives the 95th percentile
5.
百分看到定義預期結果從提供的列表,低於該值的百分之P被發現的價值。為了得到這一點,你一個簡單的函數。
def percentile(N, P):
"""
Find the percentile of a list of values
@parameter N - A list of values. N must be sorted.
@parameter P - A float value from 0.0 to 1.0
@return - The percentile of the values.
"""
n = int(round(P * len(N) + 0.5))
return N[n-1]
# A = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
# B = (15, 20, 35, 40, 50)
#
# print percentile(A, P=0.3)
# 4
# print percentile(A, P=0.8)
# 9
# print percentile(B, P=0.3)
# 20
# print percentile(B, P=0.8)
# 50
如果您寧願從處於或低於該值的百分之P被發現所提供的列表中獲得的價值,這個簡單的修改:
def percentile(N, P):
n = int(round(P * len(N) + 0.5))
if n > 1:
return N[n-2]
else:
return 0
6.
numpy.percentile
在那裡我很想念?
7.
size=len(mylist)
p5=mylist[math.ceil((size*5)/100)-1]
p25=mylist[math.ceil((size*25)/100)-1]
p50=mylist[math.ceil((size*50)/100)-1]
p75=mylist[math.ceil((size*75)/100)-1]
p95=mylist[math.ceil((size*95)/100)-1]
Ⅳ python如何定義一個函數求列表各項數據平均值
# coding = GBK
a =[1,2,3,4,5]
sum=0
b = len(a)
print("這個數組的長度為:",b)
for i in a:
sum =sum +i
print("這個數組之和為:",sum)
print("這個數組平均數為",sum/b)
或
import sys
sum = 0
cnt = 0
f = open('1.txt', 'r')
files = f.readline()
while (files ):
sum = sum + float(files .split(",")[0])
cnt = cnt + 1
files = f.readline()
print(sum / cnt)
f.close()
或者。
#!/usr/bin/env pythonimport timeimport numpy as np
dd = np.random.randint(0, 20, size=(2*1000*1000))t_start = time.clock()avg_sum1 =
0.0BlockOffset = 0 while BlockOffset < len(dd):
if dd[BlockOffset + 1] <= 10:
avg_sum1 += dd[BlockOffset + 1] * 0.1
else:
avg_sum1 += dd[BlockOffset + 0] * 0.01
BlockOffset += 2print('Avg: ' + str(avg_sum1 / len(dd) / 2)) print('Exe time: ' +
str(time.clock() - t_start))
(5)pythonmedian擴展閱讀:
python 實現求和、計數、最大最小值、平均值、中位數、標准偏差、百分比。
importsys
classStats:
def__init__(self, sequence):
# sequence of numbers we will process
# convert all items to floats for numerical processing
self.sequence=[float(item)foriteminsequence]
defsum(self):
iflen(self.sequence) <1:
returnNone
else:
returnsum(self.sequence)
defcount(self):
returnlen(self.sequence)
defmin(self):
iflen(self.sequence) <1:
returnNone
else:
returnmin(self.sequence)
defmax(self):
iflen(self.sequence) <1:
returnNone
else:
returnmax(self.sequence)
defavg(self):
iflen(self.sequence) <1:
returnNone
else:
returnsum(self.sequence)/len(self.sequence)
defmedian(self):
iflen(self.sequence) <1:
returnNone
else:
self.sequence.sort()
returnself.sequence[len(self.sequence)//2]
defstdev(self):
iflen(self.sequence) <1:
returnNone
else:
avg=self.avg()
sdsq=sum([(i-avg)**2foriinself.sequence])
stdev=(sdsq/(len(self.sequence)-1))**.5
returnstdev
defpercentile(self, percentile):
iflen(self.sequence) <1:
value=None
elif(percentile >=100):
sys.stderr.write('ERROR: percentile must be < 100. you supplied: %s '%percentile)
value=None
else:
element_idx=int(len(self.sequence)*(percentile/100.0))
self.sequence.sort()
value=self.sequence[element_idx]
returnvalue
Ⅵ 用python如何編寫
import numpy as np
n2=[]
n3=[]
n5=[]
n7=[]
while True:
s=input('請輸入')
try:
n=int(s)
if n==-1:
break
if n%2==0:
n2.append(n)
if n%3==0:
n3.append(n)
if n%5==0:
n5.append(n)
if n%7==0:
n7.append(n)
except:
print('請您輸入整數')
if len(n2)>0:
print('2的倍數有{},中位數是{},平均數是{}'.format(n2,np.median(n2),int(np.mean(n2))))
if len(n3)>0:
print('2的倍數有{},中位數是{},平均數是{}'.format(n3,np.median(n3),int(np.mean(n3))))
if len(n5)>0:
print('2的倍數有{},中位數是{},平均數是{}'.format(n5,np.median(n5),int(np.mean(n5))))
if len(n7)>0:
print('2的倍數有{},中位數是{},平均數是{}'.format(n7,np.median(n7),int(np.mean(n7))))
Ⅶ Python如何畫盒子圖與其它圖形同軸
mport pandas as pd #導入pandas
import matplotlib.pyplot as plt
import numpy as np
from scipy import interpolate
#fig,axes = plt.subplots(1,2,figsize=(8,4))
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2,sharex=True, figsize=(6, 3))
n_wrms_before_filtering=[]
e_wrms_before_filtering=[]
u_wrms_before_filtering=[]
n_wrms_after_filtering=[]
e_wrms_after_filtering=[]
u_wrms_after_filtering=[]
lines = open("D:\軟體安裝\SoftwareFile\Pycharm\PycharmProjects\\boxplot\data\wrms_neu1.dat", 'r').readlines()
for i in range(len(lines)):
# split data
fields = lines[i].split(' ')
n_wrms_before_filtering.append(float(fields[0]))
e_wrms_before_filtering.append(float(fields[1]))
u_wrms_before_filtering.append(float(fields[2]))
lines = open("D:\軟體安裝\SoftwareFile\Pycharm\PycharmProjects\\boxplot\data\wrms_neu2.dat", 'r').readlines()
for i in range(len(lines)):
# split data
fields = lines[i].split(' ')
n_wrms_after_filtering.append(float(fields[0]))
e_wrms_after_filtering.append(float(fields[1]))
u_wrms_after_filtering.append(float(fields[2]))
labels = 'N','E','U' #圖例
p1=ax1.boxplot([n_wrms_before_filtering, e_wrms_before_filtering, u_wrms_before_filtering],widths = 0.8,labels = labels,patch_artist = True)
color = ['#515151', '#f14040', '#1a6fdf'] # 有多少box就對應設置多少顏色
for box, c in zip(p1['boxes'], color):
# 箱體邊框顏色
box.set(color=c, linewidth=1.5)
# 箱體內部填充顏色
box.set(facecolor=c)
# 這里設置的是各個box的其他屬性
for whisker in p1['whiskers']:
whisker.set(color='#180405', linewidth=1.5)
for cap in p1['caps']:
cap.set(color='#180405', linewidth=1.5)
for median in p1['medians']:
median.set(color='#180405', linewidth=1.5)
for flier in p1['fliers']:
flier.set(marker='o', color='y', alpha=0.5)
labels = 'N','E','U' #圖例
p2=ax2.boxplot([n_wrms_after_filtering, e_wrms_after_filtering, u_wrms_after_filtering],widths = 0.8,labels = labels,patch_artist = True)
color = ['#515151', '#f14040', '#1a6fdf'] # 有多少box就對應設置多少顏色
for box, c in zip(p2['boxes'], color):
# 箱體邊框顏色
box.set(color=c, linewidth=1.5)
# 箱體內部填充顏色
box.set(facecolor=c)
# 這里設置的是各個box的其他屬性
for whisker in p2['whiskers']:
whisker.set(color='#180405', linewidth=1.5)
for cap in p2['caps']:
cap.set(color='#180405', linewidth=1.5)
for median in p2['medians']:
median.set(color='#180405', linewidth=1.5)
for flier in p2['fliers']:
flier.set(marker='o', color='y', alpha=0.5)
ax1.set(xlabel='Directions', ylabel='WRMS/mm')
ax2.set(xlabel='Directions', ylabel='WRMS/mm')
ax1.set_title('Before filtering')
ax2.set_title('After filtering')
plt.tight_layout()
#plt.subplots_adjust(left=0.129, bottom=0.11, right=0.9, top=0.88,wspace=0.2, hspace=0.2)
#plt.show()
plt.savefig('D:\軟體安裝\SoftwareFile\Pycharm\PycharmProjects\\boxplot\\123', dpi=600)
Ⅷ python 中一維數據中值濾波函數,在matlab中有 medfilt1函數,Python中有嗎,只找到了圖像2維的,
有的,在numpy包中
importnumpyasnp
dat=[1,3,5,6,7,2,4]
med=np.median(dat)#med=4.0
Ⅸ python用戶輸入若干個整數,按降序列印輸出在一行(使用空格間隔),並給出中位數
# coding=gbk
import numpy as np
inputStr = input("請輸入多個整數,以空格分隔:")
# 使用列表推導式將輸入的內容以空格分隔,如果有小數,則通過int函數變為整數
input_lists = [int(num) for num in inputStr.split(" ")]
# 通過sort方法,並使用參數reverse=True,來將列表的數據以降序排列
input_lists.sort(reverse=True)
# 由於通過",".join()連接的列表不能有整數元素,所以通過列表推導式將列表每個元素通過str轉為字元串後,再聯接為以逗號分隔的字元串
print(",".join([str(num) for num in input_lists]))
# 使用numpy的median函數來得到中位數
print(np.median(input_lists))
Ⅹ 請大神用Python 創建一個列表中計算中間數的函數,一定要用Python 哪!
defback_median(list_nums):
importnumpyasnp
returnnp.median(list_nums)