【转】python数据分析(分析文本数据和社交媒体)

1、安装NLTK

[html]  view plain  copy
  1. pip install nltk  

至此,我们的安装还未完成,还需要下载NLTK语料库,下载量非常大,大约有1.8GB。可以直接运行代码下载、代码如下:

[html]  view plain  copy
  1. import nltk  
  2. nltk.download()  
这样可以直接下载NLTK语料库了。

2、滤除停用词、姓名和数字

进行文本分析时,我们经常需要对停用词(Stopwords)进行剔除,这里所谓停用词就是那些非常常见,但没有多大信息含量的词。
代码:
[html]  view plain  copy
  1. import nltk  
  2. sw=set(nltk.corpus.stopwords.words('french'))  
  3. print "Stop words",list(sw)[:7]  

运行结果:
[html]  view plain  copy
  1. Stop words [u'e\xfbtes', u'\xeates', u'aient', u'auraient', u'aurions', u'auras', u'serait']  
注意,这个语料库中的所有单词都是小写形式。
nltk还提供一个Gutenberg语料库。该项目是一个数字图书馆计划,旨在收集大量版权已经过期的图书,供人们在互联网上免费阅读。下面代码是加载Gutenberg语料库,并输出部分书名的代码:
[python]  view plain  copy
  1. gb=nltk.corpus.gutenberg  
  2. print "Gutenberg files",gb.fileids()[-5:]  
运行结果:
[html]  view plain  copy
  1. Gutenberg files [u'milton-paradise.txt', u'shakespeare-caesar.txt', u'shakespeare-hamlet.txt', u'shakespeare-macbeth.txt', u'whitman-leaves.txt']  
从milton-paradise.txt中取前两个句子,并去除停用词。
代码:
[python]  view plain  copy
  1. text_sent=gb.sents("milton-paradise.txt")[:2]  #取前两个句子  
  2. print "Unfiltered:",text_sent  
  3.   
  4. for sent in text_sent:   #去除停用词  
  5.     filtered=[w for w in sent if w.lower() not in sw]  
  6.     print "Filtered:",filtered  
运行结果:
[html]  view plain  copy
  1. Filtered: [u'[', u'Paradise', u'Lost', u'John', u'Milton', u'1667', u']']  
  2. Filtered: [u'Book']  
与前面相比已经滤掉了by和I,因为他们出现在停用词语料库中,有时,我们希望把文本中的数字和姓名也删掉,可以根据词性标签来删除某些单词,数字对应基数标签(CD),姓名对应着单数形式的专有名词(NNP)标签。
代码:
[python]  view plain  copy
  1. #coding:utf8  
  2. import nltk  
  3. sw=set(nltk.corpus.stopwords.words('english'))  
  4. print "Stop words",list(sw)[:7]  
  5. gb=nltk.corpus.gutenberg  
  6. print "Gutenberg files",gb.fileids()[-5:]  
  7.   
  8. text_sent=gb.sents("milton-paradise.txt")[:2]  #取前两个句子  
  9. print "Unfiltered:",text_sent  
  10.   
  11. for sent in text_sent:   #去除停用词  
  12.     filtered=[w for w in sent if w.lower() not in sw]  
  13.     print "Filtered:",filtered  
  14.   
  15.     taggled=nltk.pos_tag(filtered)  #输出每个词的标签数据  
  16.     print "Tagged:",taggled  
  17.   
  18.     words=[]  
  19.     for word in taggled:  #过滤标签数据  
  20.         if word[1]!='NNP' and word[1]!='CD':  
  21.             words.append(word[0])  
  22.     print words  

运行结果:
[html]  view plain  copy
  1. Stop words [u'all', u'just', u'being', u'over', u'both', u'through', u'yourselves']  
  2. Gutenberg files [u'milton-paradise.txt', u'shakespeare-caesar.txt', u'shakespeare-hamlet.txt', u'shakespeare-macbeth.txt', u'whitman-leaves.txt']  
  3. Unfiltered: [[u'[', u'Paradise', u'Lost', u'by', u'John', u'Milton', u'1667', u']'], [u'Book', u'I']]  
  4. Filtered: [u'[', u'Paradise', u'Lost', u'John', u'Milton', u'1667', u']']  
  5. Tagged: [(u'[', 'JJ'), (u'Paradise', 'NNP'), (u'Lost', 'NNP'), (u'John', 'NNP'), (u'Milton', 'NNP'), (u'1667', 'CD'), (u']', 'NN')]  
  6. [u'[', u']']  
  7. Filtered: [u'Book']  
  8. Tagged: [(u'Book', 'NN')]  
  9. [u'Book']  

3、词袋模型

所谓词袋模型,即它认为一篇文档是由其中的词构成的一个集合,词与词之间没有顺序以及先后的关系。对于文档中的每个单词,我们都需要计算它出现的次数,即单词计数,据此,我们可以进行垃圾邮件识别之类的统计分析。
利用所有单词的计数,可以为每个文档建立一个特征向量,如果一个单词存在于语料库中,但是不存在于文档中,那么这个特征的值就为0,nltk中并不存在创建特征向量的应用程序,需要借助python机器学习库scikit-learn中的CountVectorizer类来轻松创建特征向量。
首先安装scikit-learn,代码:

[python]  view plain  copy
  1. pip install scikit-learn  

然后可以加载文档,去除停用词,创建向量:

[python]  view plain  copy
  1. #coding:utf8  
  2. import nltk  
  3. from sklearn.feature_extraction.text import CountVectorizer  
  4. #加载两个文档  
  5. gb=nltk.corpus.gutenberg   
  6. hamlet=gb.raw("shakespeare-hamlet.txt")  
  7. macbeth=gb.raw("shakespeare-macbeth.txt")  
  8.   
  9. #去除停用词并生成特征向量  
  10. cv=CountVectorizer(stop_words="english")  
  11. print "Feature Vector:",cv.fit_transform([hamlet,macbeth]).toarray()  

运行结果:

[html]  view plain  copy
  1. Feature Vector: [[ 1  0  1 ..., 14  0  1]  
  2.  [ 0  1  0 ...,  1  1  0]]  

4、词频分析

NLTK提供的FreqDist类可以用来将单词封装成字典,并计算给定单词列表中各个单词出现的次数。下面,我们来加载Gutenberg项目中莎士比亚的Julius Caesar中的文本。

代码:
[python]  view plain  copy
  1. #coding:utf8  
  2. import nltk  
  3. import string  
  4. gb=nltk.corpus.gutenberg  
  5. sw=set(nltk.corpus.stopwords.words('english'))  
  6. words=gb.words("shakespeare-caesar.txt")  #加载文档  
  7.   
  8. punctuation=set(string.punctuation)  #去除标点符号  
  9. filtered=[w.lower() for w in words if w.lower() not in sw and w.lower()not in punctuation]  
  10. fd=nltk.FreqDist(filtered)  #词频统计  
  11. print "Words:",fd.keys()[:5]  
  12. print "Counts:",fd.values()[:5]  
  13. print "Max:",fd.max()  
  14. print "Count",fd['pardon']  
  15.   
  16. #bigrams:对双字词进行统计分析  
  17. #trigrams:对三字词进行统计分析  
  18. fd=nltk.FreqDist(nltk.bigrams(filtered))  #对双字词进行统计分析  
  19. print "Bigrams:",fd.keys()[:5]  
  20. print "Counts:",fd.values()[:5]  
  21. print "Bigram Max:",fd.max()  
  22. print "Bigram Count",fd['decay''vseth']  

运行结果:
[html]  view plain  copy
  1. Words: [u'fawn', u'writings', u'legacies', u'pardon', u'hats']  
  2. Counts: [1, 1, 1, 10, 1]  
  3. Max: caesar  
  4. Count 10  
  5. Bigrams: [(u'bru', u'must'), (u'bru', u'patient'), (u'angry', u'flood'), (u'decay', u'vseth'), (u'cato', u'braue')]  
  6. Counts: [1, 1, 1, 1, 1]  
  7. Bigram Max: (u'let', u'vs')  
  8. Bigram Count 1  

5、朴素贝页斯分类

朴素贝页斯分类是机器学习中常见的算法,常常用于文本文档的研究,它是一个概率算法,基于概率与数理统计中的贝页斯定理。
代码:
[python]  view plain  copy
  1. #coding:utf8  
  2. import nltk  
  3. import string  
  4. import random  
  5. gb=nltk.corpus.gutenberg  
  6. sw=set(nltk.corpus.stopwords.words('english'))  
  7. punctuation=set(string.punctuation)  #去除标点符号  
  8.   
  9. def word_features(word):  #计算单词长度  
  10.     return {'len':len(word)}  
  11.   
  12. def isStopWord(word):  #判断是否是停用词  
  13.     return word in sw or word in punctuation  
  14.   
  15. words=gb.words("shakespeare-caesar.txt")  #加载文档  
  16.   
  17. labeled_words=([(word.lower(),isStopWord(word.lower())) for word in words])  
  18.   
  19. random.seed(42)  
  20. random.shuffle(labeled_words)  #元组随机排序  
  21. print labeled_words[:5]  
  22.   
  23. featuresets=[(word_features(n),word) for (n,word) in labeled_words]  
  24. cutoff=int(.9*len(featuresets))  
  25. train_set,test_set=featuresets[:cutoff],featuresets[cutoff:] #划分训练集和测试集  
  26. classifier=nltk.NaiveBayesClassifier.train(train_set)  
  27. print "'behold' class:",classifier.classify(word_features('behold'))  
  28. print "'the' class:",classifier.classify(word_features('the'))  
  29. print "Accuracy:",nltk.classify.accuracy(classifier,test_set)    #计算模型准确率  
  30. print classifier.show_most_informative_features(5)             #查看哪些特征贡献较大  
运行结果:
[html]  view plain  copy
  1. [(u'was', True), (u'greeke', False), (u'cause', False), (u'but', True), (u'house', False)]  
  2. 'behold' class: False  
  3. 'the' class: True  
  4. Accuracy: 0.857585139319  
  5. Most Informative Features  
  6.                      len = 7               False : True   =     65.7 : 1.0  
  7.                      len = 1                True : False  =     52.0 : 1.0  
  8.                      len = 6               False : True   =     51.4 : 1.0  
  9.                      len = 5               False : True   =     10.9 : 1.0  
  10.                      len = 2                True : False  =     10.4 : 1.0  

6、情感分析

随着社交媒体,产品评论网站及论坛的兴起,用来自动抽取意见的观点挖掘或情感分析也随之变成一个刺手可热的新研究领域。通常情况下,我们希望知道某个意见的性质是正面的,中立的,还是负面的。当然,这种类型的分类我们在前面就曾遇到过。也就是说,我们有大量的分类算法可用。还有一个方法就是,通过半自动(经过某些人工编辑)方法来编制一个单词列表,每个单词赋予一个情感分,即一个数值(单词“good“的情感分为5,而单词”bad“的情感分为-5)。如果有了这样一张表,就可以给文本文档中的所有单词打分,从而得出一个情感总分。当然,类别的数量可以大于3,如五星级分级方案。
我们会应用朴素贝叶斯分类方法对NLTK的影评语料进行分析,从而将影评分为正面的或负面的评价。首先,加载影评语料库,并过滤掉停用词和标点符号。这些步骤在此省略,因为之前就介绍过。也可以考虑更精细的过滤方案。不过,需要注意的是,如果过滤得过火了,就会影响准确性,

[python]  view plain  copy
  1. #coding:utf8  
  2. import random  
  3. from  nltk.corpus import movie_reviews  
  4. from nltk.corpus import stopwords  
  5. from nltk import FreqDist  
  6. from nltk import NaiveBayesClassifier  
  7. from nltk.classify import accuracy  
  8. import string  
  9.   
  10.   
  11. #使用categories  
  12. labeled_docs=[(list(movie_reviews.words(fid)),cat)  
  13.                 for cat in movie_reviews.categories()  
  14.                 for fid in movie_reviews.fileids(cat)]  
  15. random.seed(42)  
  16. random.shuffle(labeled_docs)  
  17. #print labeled_docs[:1]  
  18. review_words=movie_reviews.words()  
  19. print "# Review Words:",len(review_words)  
  20.   
  21. sw=set(stopwords.words('english'))  
  22. punctuation=set(string.punctuation)  #去除标点符号  
  23. def isStopWord(word):  #判断是否是停用词  
  24.     return word in sw or word in punctuation  
  25. filtered=[w.lower() for w in review_words if not isStopWord(w.lower())]  
  26. print "#After filter:",len(filtered)  #去除停用词后的长度  
  27.   
  28. words=FreqDist(filtered)  #词频统计  
  29. N=int(0.05*len(words.keys()))  
  30. word_features=words.keys()[:N]  
  31.   
  32. def doc_features(doc):  
  33.     doc_words=FreqDist(w for w in doc if not isStopWord(w))  
  34.     features={}  
  35.     for word in word_features:  
  36.         features['count (%s)'%word]=(doc_words.get(word,0))  
  37.     return features  
  38.   
  39. featuresets=[(doc_features(d),c) for (d,c) in labeled_docs]  
  40. train_set,test_set=featuresets[200:],featuresets[:200]  
  41. classifier=NaiveBayesClassifier.train(train_set)  
  42. print "Accuracy",accuracy(classifier,test_set)  
  43.   
  44. print classifier.show_most_informative_features()  

运行结果:
[python]  view plain  copy
  1. # Review Words: 1583820  
  2. #After filter: 710579  
  3. Accuracy 0.695  
  4. Most Informative Features  
  5.           count (nature) = 2                 pos : neg    =      8.5 : 1.0  
  6.              count (ugh) = 1                 neg : pos    =      8.2 : 1.0  
  7.             count (sans) = 1                 neg : pos    =      8.2 : 1.0  
  8.     count (effortlessly) = 1                 pos : neg    =      6.3 : 1.0  
  9.       count (mediocrity) = 1                 neg : pos    =      6.2 : 1.0  
  10.        count (dismissed) = 1                 pos : neg    =      5.8 : 1.0  
  11.             count (wits) = 1                 pos : neg    =      5.8 : 1.0  
  12.             count (also) = 6                 pos : neg    =      5.8 : 1.0  
  13.             count (want) = 3                 neg : pos    =      5.5 : 1.0  
  14.             count (caan) = 1                 neg : pos    =      5.5 : 1.0  

7、创建词云

可以直接利用wordle网站在线创建词云,地址:http://www.wordle.net/advanced。网站需要支持Java插件,最好使用MAC的Safari浏览器。利用Wordle生成词云时,需要提供一个单词列表及其对应的权值,具体格式为
word1 : weight
       word2  :weight
利用之前代码,生成词频,代码如下:
[python]  view plain  copy
  1. #coding:utf8  
  2. import random  
  3. from  nltk.corpus import movie_reviews  
  4. from nltk.corpus import stopwords  
  5. from nltk import FreqDist  
  6. from nltk import NaiveBayesClassifier  
  7. from nltk.classify import accuracy  
  8. import string  
  9.   
  10.   
  11. sw=set(stopwords.words('english'))  
  12. punctuation=set(string.punctuation)  #去除标点符号  
  13. def isStopWord(word):  #判断是否是停用词  
  14.     return word in sw or word in punctuation  
  15. review_words=movie_reviews.words()  
  16. filtered=[w.lower() for w in review_words if not isStopWord(w.lower())]  
  17. #print filtered  
  18.   
  19. words=FreqDist(filtered)  #词频统计  
  20. N=int(0.01*len(words.keys()))  
  21. tags=words.keys()[:N]  
  22.   
  23. for tag in tags:  
  24.     print tag,":",words[tag]  

将上面运行结果复制粘贴到wordle页面,就可以得到如下词云图:



仔细研究这个词云图,发现并不完美,还有很大改进空间。因此可以进一步改进:
进一步过滤:剔除包含数字字符和姓名的单词,可以借助NLTK的names语料库。此外,对于只出现一次的单词,可以置之不理,因为不太可能提供足够有价值的信息。
使用更好的度量标签:词频和逆文档频率(TF-IDF)
度量指标TF-IDF可以通过对语料库的单词进行排名,并据此赋予这些单词相应的权重。这些权重的值与单词在特定文档中出现的次数即词频成正比。同时,它还与语料库中含有改单词的文档数量成反比,及逆文档频率。TF-IDF的值为词频和逆文档频率之积。如果需要自己动手实现TF-IDF,那么还必须考虑对数标处理,幸运的是,scikit-learn已经为我们准备好了一个TfidfVectorizer类,它有效实现了TF-IDF。
代码:
[html]  view plain  copy
  1. #coding:utf8  
  2. import random  
  3. from  nltk.corpus import movie_reviews  
  4. from nltk.corpus import stopwords  
  5. from nltk.corpus import names  
  6. from nltk import FreqDist  
  7. from nltk import NaiveBayesClassifier  
  8. from nltk.classify import accuracy  
  9. from sklearn.feature_extraction.text import TfidfVectorizer  
  10. import itertools  
  11. import pandas as pd   
  12. import numpy as np   
  13. import string  
  14.   
  15.   
  16. sw=set(stopwords.words('english'))  
  17. punctuation=set(string.punctuation)  #去除标点符号  
  18. all_names=set([name.lower() for name in names.words()])   #得到所有名字信息  
  19.   
  20. def isStopWord(word):  #判断是否是停用词   isalpha函数判断字符是否都是由字母组成  
  21.     return (word in sw or word in punctuation or word in all_names or not word.isalpha())  
  22. review_words=movie_reviews.words()  
  23. filtered=[w.lower() for w in review_words if not isStopWord(w.lower())]  
  24. #print filtered  
  25.   
  26. words=FreqDist(filtered)  #词频统计  
  27. texts=[]  
  28. for fid in movie_reviews.fileids():  
  29.     #print fid     fid表示文件  
  30.     texts.append(" ".join([w.lower() for w in movie_reviews.words(fid) if not isStopWord(w.lower()) and words[w.lower()]>1]))  
  31.   
  32. vectorizer=TfidfVectorizer(stop_words='english')  
  33. matrix=vectorizer.fit_transform(texts)   #计算TD-IDF  
  34. #print matrix  
  35.   
  36. sums=np.array(matrix.sum(axis=0)).ravel()  #每个单词的TF-IDF值求和,并将结果存在numpy数组  
  37. ranks=[]  
  38. #itertools.izip把不同的迭代器的元素聚合到一个迭代器中。类似zip()方法,但是返回的是一个迭代器而不是一个list  
  39. for word, val in itertools.izip(vectorizer.get_feature_names(),sums):  
  40.     ranks.append((word,val))  
  41.   
  42. df=pd.DataFrame(ranks,columns=["term","tfidf"])  
  43. df=df.sort_values(['tfidf'])  
  44.   
  45. #print df.head()  
  46.   
  47. N=int(0.01*len(df))  #得到排名靠前的1%  
  48. df=df.tail(N)  
  49.   
  50.   
  51. for term,tfidf in itertools.izip(df["term"].values,df["tfidf"].values):  
  52.     print term,":",tfidf  
  53. tags=words.keys()[:N]  
  54.   
  55. # for tag in tags:  
  56. #   print tag,":",words[tag]  

同样放到wordle中生成词云图:

8、社交网络分析

所谓社交网络分析,实际上就是利用网络理论来研究社会关系。其中网络的节点代表的是网络中的参与者。节点之间的连线代表的是参与者之间的相互关系。本节介绍如何使用Python库NetworkX来分析简单的图。并通过matplotlib库对这些网络图可视化。
安装networkx:pip install networkx

networkx提供许多示例图,可以列出,具体代码如下:
[html]  view plain  copy
  1. #coding:utf8  
  2. import networkx as nx  
  3. #networkx提供许多示例图,可以列出  
  4. print [s for s in dir(nx) if s.endswith('graph')]  
运行结果:
[html]  view plain  copy
  1. ['LCF_graph', 'adjacency_graph', 'barabasi_albert_graph', 'barbell_graph', 'binomial_graph', 'bull_graph', 'caveman_graph', 'chordal_cycle_graph', 'chvatal_graph', 'circulant_graph', 'circular_ladder_graph', 'complete_bipartite_graph', 'complete_graph', 'complete_multipartite_graph', 'connected_caveman_graph', 'connected_watts_strogatz_graph', 'cubical_graph', 'cycle_graph', 'cytoscape_graph', 'davis_southern_women_graph', 'dense_gnm_random_graph', 'desargues_graph', 'diamond_graph', 'digraph', 'directed_havel_hakimi_graph', 'dodecahedral_graph', 'dorogovtsev_goltsev_mendes_graph', 'duplication_divergence_graph', 'edge_subgraph', 'ego_graph', 'empty_graph', 'erdos_renyi_graph', 'expected_degree_graph', 'extended_barabasi_albert_graph', 'fast_gnp_random_graph', 'florentine_families_graph', 'frucht_graph', 'gaussian_random_partition_graph', 'general_random_intersection_graph', 'geographical_threshold_graph', 'gn_graph', 'gnc_graph', 'gnm_random_graph', 'gnp_random_graph', 'gnr_graph', 'graph', 'grid_2d_graph', 'grid_graph', 'havel_hakimi_graph', 'heawood_graph', 'hexagonal_lattice_graph', 'hoffman_singleton_graph', 'house_graph', 'house_x_graph', 'hypercube_graph', 'icosahedral_graph', 'induced_subgraph', 'is_directed_acyclic_graph', 'jit_graph', 'joint_degree_graph', 'json_graph', 'k_random_intersection_graph', 'karate_club_graph', 'kl_connected_subgraph', 'krackhardt_kite_graph', 'ladder_graph', 'line_graph', 'lollipop_graph', 'make_max_clique_graph', 'make_small_graph', 'margulis_gabber_galil_graph', 'moebius_kantor_graph', 'multidigraph', 'multigraph', 'navigable_small_world_graph', 'newman_watts_strogatz_graph', 'node_link_graph', 'null_graph', 'nx_agraph', 'octahedral_graph', 'pappus_graph', 'partial_duplication_graph', 'path_graph', 'petersen_graph', 'planted_partition_graph', 'powerlaw_cluster_graph', 'projected_graph', 'quotient_graph', 'random_clustered_graph', 'random_degree_sequence_graph', 'random_geometric_graph', 'random_k_out_graph', 'random_kernel_graph', 'random_partition_graph', 'random_regular_graph', 'random_shell_graph', 'relabel_gexf_graph', 'relaxed_caveman_graph', 'scale_free_graph', 'sedgewick_maze_graph', 'star_graph', 'stochastic_graph', 'subgraph', 'tetrahedral_graph', 'to_networkx_graph', 'tree_graph', 'triad_graph', 'triangular_lattice_graph', 'trivial_graph', 'truncated_cube_graph', 'truncated_tetrahedron_graph', 'turan_graph', 'tutte_graph', 'uniform_random_intersection_graph', 'watts_strogatz_graph', 'waxman_graph', 'wheel_graph', 'windmill_graph']  

导入davis_southern_women_graph,并绘制各个节点的度的柱状图,代码如下:
[python]  view plain  copy
  1. G=nx.davis_southern_women_graph()  
  2. plt.figure(1)  
  3. a={}  
  4. a=dict(nx.degree(G))  
  5. plt.hist(a.values())  
运行结果:

下面绘制带节点标签的网络图,代码如下:
[html]  view plain  copy
  1. plt.figure(2)  
  2. pos=nx.spring_layout(G)  
  3. nx.draw(G,node_size=9)  
  4. nx.draw_networkx_labels(G,pos)  
  5. plt.show()  
运行结果:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值