DataWhale零基础入门NLP赛事系列——Task2数据读取与分析

数据读取

用pandas读取数据

train_df = pd.read_csv('data/train_set.csv', sep='\t')
print(train_df.head())

这里的read_csv由两部分组成:

  1. 第一个参数是你数据文件的路径,根据自己的实际情况修改成绝对路径或者相对路径;
  2. 分隔符sep : 每列分割的字符,此处设置为\t
  3. 还有一个参数,这里面没用。nrows是此次读取文件的函数,限制读取的记录数量。如果nrows=100代表读取文件的前100行。

读取数据的时候我遇到了一个问题,label和text之间总是有\t,以至于不能得到一个正常的DataFrame。我用其他的方法处理之后才得到如下数据:

   label                                               text
0      2  2967 6758 339 2021 1854 3731 4109 3792 4149 15...
1     11  4464 486 6352 5619 2465 4802 1452 3137 5778 54...
2      3  7346 4068 5074 3747 5681 6093 1777 2226 7354 6...
3      2  7159 948 4866 2109 5520 2490 211 3956 5520 549...
4      3  3646 3055 3055 2490 4659 6065 3370 5814 2465 5...

但是看过教程以后,只需一个sep='\t'便解决了数据读取的问题。

数据分析

在读取完数据集以后,首先应该进行数据分析,这是比赛中拿到数据的一般步骤。文本数据是一种非结构化的数据,也许不需要做出很多的分析,但是通过数据分析可以找到一些规律。

至于找哪些规律,这个一般参加比赛多了更能准确找到思路。在此作为一个NLP的小小白,参考了教程的内容:

  1. 赛题数据中,新闻文本的长度是多少? 如果文本很长的话不利于训练,所以需要对文本进行分割;
  2. 数据集中类别是如何分布的,哪种类别最多,哪种类别最少;
  3. 数据集中字符是怎样分布的? (这个的出发点应该是找到标点符号,如果出现的频率覆盖了全部的新闻,估计就有可能是标点符号)
文本长度分析

数据集中每个text都是用字符之间都是空格分开的,所以可以统计字符的个数来得到每个句子的长度。首先分析了Text的类型:print(type(train_df['text'][0]))
得到是<class 'str'>,因此可以直接使用split()函数。统计代码及结果如下:

train_df['text_len'] = train_df['text'].apply(lambda x: len(x.split(' ')))
print(train_df['text_len'].describe())

统计结果:

count    200000.000000
mean        907.207110
std         996.029036
min           2.000000
25%         374.000000
50%         676.000000
75%        1131.000000
max       57921.000000
Name: text_len, dtype: float64

对新闻文本分析可以看出,平均每个新闻文本的长度是907,新闻最长是57921,最短是2.整体来看文本还是比较长的。统计文本长度的直方图如下:

_ = plt.hist(train_df['text_len'], bins=100)
plt.xlabel('Text char count')
plt.title("Histogram of char count")
plt.show()

大部分句子长度都在2000以内。

新闻类别分布

对新闻的类别进行分布统计,统计每类新闻的样本个数。

# 统计每类新闻样本个数
train_df['label'].value_counts().plot(kind='bar')
plt.title('News class count')
plt.xlabel("category")
plt.show()

在这里插入图片描述
从统计结果可以看出,数据集类别分布存在较为不均匀的情况。在训练集中科技类新闻最多,其次是股票类新闻,最少的新闻是星座新闻。

字符分布统计

要统计每个字符出现的次数,首先将所有文本进行拼接进而划分为字符,再对字符进行统计。

all_lines = ' '.join(list(train_df['text']))
word_count = Counter(all_lines.split(" "))
word_count = sorted(word_count.items(), key=lambda d:d[1], reverse = True)

print(len(word_count))

print(word_count[0])

print(word_count[-1])

从统计结果来看,训练集总共包括6869个字符,字符编号3750的出现的次数最多为7482224次,字符编号3133的出现的次数最少为1次。
在这里插入图片描述
**重点:**可以根据字符在每个句子中出现的情况反推出标点符号。下面统计了不同字符在句子中出现的次数。

# 统计不同字符在每个句子中出现的次数
train_df['text_unique'] = train_df['text'].apply(lambda x: ' '.join(list(set(x.split(' ')))))
all_lines = ' '.join(list(train_df['text_unique']))
word_count = Counter(all_lines.split(" "))
word_count = sorted(word_count.items(), key=lambda d:int(d[1]), reverse = True)

print(word_count[0])

根据统计结果可以看出3750,900,648的覆盖率达到了99%(一共20W条数据),推断出这三个字符可能是标点符号。但是900和648出现了多次连续的情况,因此判断这两个都不能是句子的结束符号,因此大胆推测3750为句子的结束符号。

('3750', 197997)
('900', 197653)
('648', 191975)

作业:

  1. 假设字符3750,字符900和字符648是句子的标点符号,请分析赛题每篇新闻平均由多少个句子构成?
  2. 统计每类新闻中出现次数对多的字符

我在之前将每个文本以3750作为结束符进行了处理,将每篇新闻的句子数量保存到了sentence_num.csv中,针对作业一:

# 求平均每篇新闻有多少个句子
col_name = ['sentence_num']
sen_num = pd.read_csv('data/sentence_num.csv',names=col_name)
sen_sum = sum(sen_num['sentence_num'])
sen_ave = sen_sum / sen_num.shape[0]
print('句子个数之和:{}'.format(sen_sum))
print('一共有{}篇新闻'.format(sen_num.shape[0]))
print('平均每篇新闻中句子个数为:{}'.format(sen_ave))

结果如下:
在这里插入图片描述
针对作业二,首先将数据按类别拼接到一起,

# 不同新闻分割,按标签排序
new_df = df.sort_values(by='label',ascending=True)

找出每个类别第一条记录的索引,再分别求出每类新闻出现次数最多的字符。

# label:index  1:38918,2:75863,3:107288,4:129421,5:144437,6:156669,7:166654,8:175495,9:183342,10:189220\
# 11:194140,12:197271,13:199092

拿体育新闻举例:

for i,row in sorted_df[75863:107288].iterrows():
    text = str(row['text'])
    text =text.split()
    for j,word in enumerate(text):
        word = int(word)
        word_list.append(word)

# 去重
sorted_list,word_uni = np.unique(word_list, return_counts=True)

print(type(word_uni))
word_uni_list = word_uni.tolist()
sorted_list = sorted_list.tolist()

#出现对多的是一个符号,去掉

id_num_list = [sorted_list.index(i) for i in [3750,900,648]]
print(id_num_list)
for i in id_num_list:
    del word_uni_list[i]
    del sorted_list[i]
max_num = max(word_uni_list)
id_num = word_uni_list.index(max(word_uni_list))
max_word = sorted_list[id_num]

print("体育类新闻出现字符次数最多的个数:{}".format(max_num))
print("体育类新闻出现字符次数最多的字符:{}".format(max_word))

结果如下:

科技类新闻出现字符次数最多的个数:502377
科技类新闻出现字符次数最多的字符:3370
股票类新闻出现字符次数最多的个数:557924
股票类新闻出现字符次数最多的字符:3370
体育类新闻出现字符次数最多的个数:351374
体育类新闻出现字符次数最多的字符:7399
娱乐类新闻出现字符次数最多的个数:187649
娱乐类新闻出现字符次数最多的字符:6122
时政类新闻出现字符次数最多的个数:119816
时政类新闻出现字符次数最多的字符:4411
社会类新闻出现字符次数最多的个数:158747
社会类新闻出现字符次数最多的字符:6122
教育类新闻出现字符次数最多的个数:192903
教育类新闻出现字符次数最多的字符:6248
财经类新闻出现字符次数最多的个数:158280
财经类新闻出现字符次数最多的字符:3370
家居类新闻出现字符次数最多的个数:56590
家居类新闻出现字符次数最多的字符:6122
游戏类新闻出现字符次数最多的个数:46230
游戏类新闻出现字符次数最多的字符:7328
房产类新闻出现字符次数最多的个数:67544
房产类新闻出现字符次数最多的字符:3370
时尚类新闻出现字符次数最多的个数:18591
时尚类新闻出现字符次数最多的字符:4939
彩票类新闻出现字符次数最多的个数:51343
彩票类新闻出现字符次数最多的字符:4464
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值