受刘思喆大佬一篇文章《爱情永远寂寞》的启发,对其中的文本挖掘技术非常感兴趣,遂产生了复制这个分析的想法。最近我一直在阅读各种各样的有趣分析,或者是Kaggle Notebooks,其中若有我比较感兴趣的主题、数据、算法,我都会尝试复现一下。

比如《爱情永远寂寞》这篇文章中提到的:

拿到22996 首中文歌曲(844 个流行歌手)之后,总觉得在这些非结构化数据背后肯定隐藏了什么,但到底会有什么模式呢?当经历了分词、构建矩阵、去除停止词、矩阵约减,最终通过模式识别,统计数字之后爱情居然是这样的一个真相

看上去还挺复杂的有没有?我之前只接触过Text Mining with R 这本书提供的方法,也就是构建N-gram。也不知道上边说的“构建矩阵”、“矩阵约减”、“模式识别”之类的方法怎么实现。但目前确定的是构建N-gram能够给出类似的文本词语关联关系。

这篇文章并没有给出分析用的原始代码及数据。那么复现类似的分析需要自己找一份歌词数据。在github上搜了一下,找到的是这个repo中所用的数据:

https://github.com/liuhuanyong/MusicLyricChatbot

数据是json格式的。首先我使用了Python读入json数据,使用jieba工具进行汉语分词。Python程序如下:

import jieba
import json
import time
import gc
import pandas as pd
import matplotlib.pyplot as pltstopword_list = [k.strip() for k in open('../input/english-and-chinese-stopwords/stopwords.txt', encoding='utf8').readlines() if k.strip() != '']music = []
for line in open('../input/chinese-pop-song-lyrics/music.json','r'):music.append(json.loads(line))print('json文件总长度 {} '.format(len(music)))
# json文件总长度 140068 lyrics = []
for i in music:lyrics.append(i['geci'])def generate_ngrams(text, n_gram=2):'''得到N元组'''token = [k for k in jieba.cut(text) if k.isspace() == False if k != ''  and k not in stopword_list]ngrams = zip(*[token[i:] for i in range(n_gram)])single = ['_'.join(j) for j in ngrams if j != '' and j not in stopword_list]return singlegenerate_ngrams('难道我怕找不到更好', 3)
# ['难道_我怕_找', '我怕_找_不到', '找_不到_更好']

上面展示了N元组(n-gram)函数,N元组反映了一句话中词语的顺序关系。对于“难道我怕找不到更好”这一句话来说,可以分成这样的二元组['难道_我怕', '我怕_找', '找_不到', '不到_更好'],三元组:['难道_我怕_找', '我怕_找_不到', '找_不到_更好']。通过对数据集中的每一句歌词进行这样的处理,构建大量的二元组,并且根据出现的频率筛选掉长尾二元组,我们可以构建出一个比较有代表性的文本网络。

gramList = []start = time.time()
for song in lyrics:songlist = []for line in song:ngram = generate_ngrams(line)songlist.extend(ngram)gramList.extend(songlist)
print('this program costs {:.2f} seconds'.format(time.time() - start))
# this program costs 1415.58 secondslen(gramList)gramDt = pd.DataFrame(gramList)
del gramList
gc.collect()
gramDt.columns = ['bigram']gramDt['word1'] = gramDt['bigram'].apply(lambda x: x.split('_')[0])
gramDt['word2'] = gramDt['bigram'].apply(lambda x: x.split('_')[1])
gramDt#     bigram  word1   word2
# 0 玫瑰_多情   玫瑰  多情
# 1 多情_刺    多情  刺
# 2 刺_竟 刺   竟
# 3 竟_奶 竟   奶
# 4 奶_似曾相识  奶   似曾相识
# ...   ... ... ...
# 14821649  话题_什么   话题  什么
# 14821650  什么_看法   什么  看法
# 14821651  看法_欢迎   看法  欢迎
# 14821652  欢迎_留言   欢迎  留言
# 14821653  留言_交流   留言  交流gramDt.to_csv('gramDt.csv', index=False)

最后我们得到了如上所示的数据框并且保存成csv格式。本来我计划将所有分析都放在Python中完成,但当我进行绘图的时候,我发现Python的图形工具并不好用。在对中文的支持方面,Python真的不够出色。这是我无法解决的问题。因此我只好将数据存下来使用R语言进一步分析。

library(data.table)
library(igraph)gramDt = read.csv("./gramDt.csv", encoding="UTF-8")
gramDt = as.data.table(gramDt)
gramDt = gramDt[,.(n = .N), by=c('word1', 'word2')] # 根据二元组计算词频head(gramDt, 150)
setorder(gramDt, -n)gramDt = gramDt[ !grepl("^([a-zA-Z0-9])", x=word1), ]
gramDt = gramDt[ !grepl("^([a-zA-Z0-9])", x=word2), ]# 筛选日文
gramDt = gramDt[ !grepl('[\u3040-\u309Fー]+', x=word1), ]
gramDt = gramDt[ !grepl('[\u3040-\u309Fー]+', x=word2), ]
gramDt = gramDt[ !grepl( '[\u30A0-\u30FF]+', x=word1), ]
gramDt = gramDt[ !grepl( '[\u30A0-\u30FF]+', x=word2), ]# 筛选韩文
gramDt = gramDt[ !grepl( '[\u3130-\u318F\uAC00-\uD7AF]+', x=word1), ]
gramDt = gramDt[ !grepl( '[\u3130-\u318F\uAC00-\uD7AF]+', x=word2), ]gramDt = gramDt[!(word1==word2),]symbol = c('?', '卐','(',')','!', '々', '∶',':','★','☆','@','#',';','←','√','к','и','壳','日', '発', '売')
gramDt = gramDt[ !word1 %in% symbol, ]
gramDt = gramDt[ !word2 %in% symbol, ]

以上是使用R语言进行进一步数据清理的代码。可以看到我使用了大量正则表达式来筛选掉日文韩文。这是因为数据集中混杂了大量其他语言的歌曲,需要将非汉语的内容全部去掉。这里实际上是前期探索性数据分析的缺失导致的,由于一开始不知道数据的全貌,导致分析后期才发现多语种的混杂问题。

接下来我们需要筛选掉过于长尾的词组,保留高频词组。igraph::graph_from_data_frame()函数能够从数据框中生成图结构。plot()泛型函数能够提供图的各种定制化修改。这里我们使用rescale方法按照词频显示汉字的大小。

gramDt = gramDt[n>700,]
setcolorder(gramDt, c("word1", "word2", "n"))lyricgram = graph_from_data_frame(gramDt, directed=F)rescale = function(x,a,b,c,d){c + (x-a)/(b-a)*(d-c)}
plot(lyricgram,vertex.size=2, vertex.label.dist=0.9,vertex.label.color='purple',vertex.color='blue',vertex.shape='circle',edge.color='grey',vertex.label.cex=rescale(degree(lyricgram), 1, 24, 0.5, 1), layout = layout.fruchterman.reingold
)

输出的图形如下:

总体而言,“爱”在中文流行歌曲中占据非常重要的地位。相当多的词语都围绕着“爱”这个主题。其次,一些介词(比如“里”、“中”、“不要”、“会”)连接了其他主题。这可能是一种伪关联。或许通过其他方法,能够揭示出词语间更为本质的联系。可能因为数据的不同,这个分析结果并未复现出刘思喆文中“爱情永远寂寞”的主题。总体而言,这是一次对文本网络进行分析的尝试。实际上影响结果的还有很多“超参数”,比如N元组的选取(本次分析仅选择了2元组)、分词方式的选取、对词的筛选等等,这些都需要仔细地调节。


扫码关注微信公众号ApocalypseNow,分享好玩有趣的数据分析

中文流行歌曲歌词文本挖掘相关推荐

  1. 08年09年最好听的中文流行歌曲大全

    08年09年中文流行歌曲排行TOP100 1. 脚本 (王力宏) 2. 一瞬间 (张靓颖) 3. 高调爱 (罗志祥) 4. 快乐英雄 (潘玮柏) 5. 火星爱月亮 (黄雅莉) 6. 信以为真 (尚雯婕 ...

  2. 打上花火中文谐音歌词_【1分钟学会闽南语歌】茄子蛋-《浪子回头》-闽南语音译歌词视频...

    茄子蛋-浪子回头-谐音版https://www.zhihu.com/video/1171844014985891840茄子蛋-<浪子回头>-闽南语中文音译歌词谐音发音-歌曲谐音网​www. ...

  3. 打上花火(打ち上げ花火) --罗马音歌词中文谐音歌词

    罗马音歌词 a no hi mi wa ta shi ta na gi sa i ma mo o mo i da sun da su na no u e ni ki za n da ko to ba ...

  4. 用计算机唱起了98k,抖音98k歌曲原名叫什么谐音怎么唱 98k歌曲中文谐音歌词

    抖音98k歌曲很火,不过因为98k是首英文歌,很多小伙伴不会唱,抖音98k中文谐音怎么唱?下面带来抖音98k歌曲中文谐音歌词. 抖音98k谐音怎么唱 玩抖音的小伙伴应该都听过98k歌曲,这首歌曲原名叫 ...

  5. animals中文谐音_animals中文谐音_张杰pretty white lies中文音译歌词

    Pretty White Lies[1]- 张杰 OA(原词):Nick Atki/nson/Edd Holloway/Jake Roche/Danny Wilkin/Charley Bagnall/ ...

  6. troublemaker中文谐音_饿狼传说谐音歌词

    饿狼传说她熄掉晚灯幽幽掩两肩交织了火花拘禁在沉淀心刚被割损经不起变迁她偏以指尖牵引著磁电汹涌的爱扑着我尽力乱吻缠!偏偏知道,爱令我无明天!他倚着我肩呼吸响耳边高温已产生色相令人乱君子在摸火吹不走暖烟她 ...

  7. 用计算机弹出thatgirl,抖音thatgirl谐音唱法音译 thatgirl歌词是什么意思中文翻译...

    About that girl the one I let get away(那个女孩 我们曾擦肩而过)I keep saying no(我一直否认)This can't be the way we' ...

  8. 文本挖掘技术在CIC的应用--转载

    数据挖掘(Data Mining)已经不是一个新鲜的概念,"尿布和啤酒" 这一经典案例也被很多人津津乐道: 美国一家大型超市利用数据挖掘技术来分析他们的销售纪录,居然发现尿布和啤酒 ...

  9. 基于中文主观性知识库的句子主观性计算项目

    ChineseZhuguanDectection 项目地址:https://github.com/liuhuanyong/ZhuguanDetection Chinese Subjective Dec ...

最新文章

  1. java word 读取excel数据_在Java中实现读写操作Word、Excel等文件
  2. 正则表达式需要转义的字符
  3. 数据结构的简单理解(4)
  4. Akka笔记–演员介绍
  5. c语言定义数组6,C语言教程6数组.ppt
  6. UITableView 系列五 :自定义UITableViewCell (实例)
  7. 训练dnn_[预训练语言模型专题] MT-DNN(KD) : 预训练、多任务、知识蒸馏的结合
  8. 五、String字符串常用方法
  9. Unity如何调用安卓手机摄像头实现拍照和录像
  10. LNK2005 protected: virtual int __thiscall CDataView::OnInitDialog(void) (?OnInitDialog@CDataVie
  11. 算法竞赛入门经典(第二版)_1入门
  12. 朴树歌词分析--python爬虫
  13. [并查集]BZOJ 1050——[HAOI2006]旅行comf
  14. Ubuntu系统显示实时网速信息
  15. telnet测试136邮箱imap服务器
  16. 最佳治理实践?一文读懂YFI运行机制
  17. 【Rust日报】2020-11-09 构建可测试性的 Rust 工程
  18. ExoPlayer的缓存 三 SimpleCache的使用
  19. B2B 手动客户端网络上传数据报错:由于目标机器积极拒绝,无法连接,解决办法
  20. Echarts canvas渲染出来的图表与边框的距离修改

热门文章

  1. Java命名规范你一定要掌握
  2. 中科大少年班,官方公布48名新生名单,有人因偶像曹原,有人只是不想经历高三...
  3. [译] 自然语言处理真是有趣!
  4. 小兵大乱斗服务器维修吗,小兵大乱斗新手怎么玩 小兵大乱斗新萌扫盲攻略
  5. 计算机网络实验软件工具
  6. Ubuntu Linux的安装
  7. 计算公元纪年法总天数及星期几(用自己的一个思路)查询日历保存到文本文件
  8. 解决Chrome浏览器翻译无法使用的问题
  9. 都说找工作难, 你真的好好准备了吗?
  10. 朱算子谈命理:我们应该怎样看待命理