在Matlab中计算bigrams的频率

时间:2014-09-12 10:53:02

标签: matlab

我正在尝试计算和绘制bigrams频率的分布 首先,我确实生成了所有可能的bigrams,它们提供了1296个双字母

然后我从给定文件中提取bigrams并将其保存在words1

我的问题是如何为文件a.txt计算这1296个双子星的频率? 如果文件中根本没有出现一些双字母,那么它们的频率应为零

a.txt是任何文本文件

clear
clc
%************create bigrams 1296 ***************************************
chars ='1234567890abcdefghijklmonpqrstuvwxyz';
chars1 ='1234567890abcdefghijklmonpqrstuvwxyz';
bigram='';
for i=1:36
for j=1:36

bigram = sprintf('%s%s%s',bigram,chars(i),chars1(j));

end
end
temp1 = regexp(bigram, sprintf('\\w{1,%d}', 1), 'match');
temp2 = cellfun(@(x,y) [x '' y],temp1(1:end-1)', temp1(2:end)','un',0);
bigrams = temp2;
bigrams = unique(bigrams);
bigrams =  rot90(bigrams);
bigram = char(bigrams(1:end));
all_bigrams_len = length(bigrams);
clear temp temp1 temp2 i j chars1 chars;

%****** 1. Cleaning Data ******************************
collection = fileread('e:\a.txt');
collection = regexprep(collection,'<.*?>','');
collection = lower(collection);
collection = regexprep(collection,'\W','');
collection = strtrim(regexprep(collection,'\s*',''));

%*******************************************************

temp = regexp(collection, sprintf('\\w{1,%d}', 1), 'match');
temp2 = cellfun(@(x,y) [x '' y],temp(1:end-1)', temp(2:end)','un',0);
words1 = rot90(temp2);

%*******************************************************
words1_len = length(words1);
vocab1 = unique(words1);
vocab_len1 = length(vocab1);
[vocab1,void1,index1] = unique(words1);
frequencies1 = hist(index1,vocab_len1);

5 个答案:

答案 0 :(得分:2)

嘿,类似于Dennis解决方案,你可以使用histc()

string1 = 'ASHRAFF'
histc(string1,'ABCDEFGHIJKLMNOPQRSTUVWXYZ')

这会检查由字符串'ABCDEFGHIJKLMNOPQRSTUVWXYZ'定义的区间中的条目数,这有希望是字母表(只是快速写入,所以没有保证)。结果是:

  Columns 1 through 21

     2     0     0     0     0     2     0     1     0     0     0     0     0     0     0     0     0     1     1     0     0

  Columns 22 through 26

     0     0     0     0     0

对我的解决方案进行一点修改:

string1 = 'ASHRAFF'
alphabet1='A':'Z'; %%// as stated by Oleg Komarov
data=histc(string1,alphabet1);
results=cell(2,26);
for k=1:26
    results{1,k}= alphabet1(k);
    results{2,k}= data(k);
end

如果你现在看results,你可以很容易地检查它是否有效:D

答案 1 :(得分:2)

予。字符串的字符计数问题

基于

bsxfun的计算字符数的解决方案 -

counts = sum(bsxfun(@eq,[string1-0]',65:90))

输出 -

counts =

    2     0     0     0     0     2     0     1     0     0 ....

如果您希望得到每个字母的计数表格 -

out = [cellstr(['A':'Z']') num2cell(counts)']

输出 -

out = 
    'A'    [2]
    'B'    [0]
    'C'    [0]
    'D'    [0]
    'E'    [0]
    'F'    [2]
    'G'    [0]
    'H'    [1]
    'I'    [0]

....

请注意,这是对大写字母区分大小写的计数。

对于小写字母计数,请将此编辑用于此早期代码 -

counts = sum(bsxfun(@eq,[string1-0]',97:122))

对于不区分大小写的计数,请使用此 -

counts = sum(bsxfun(@eq,[upper(string1)-0]',65:90))

II。 Bigram计算案例

让我们假设您已将所有可能的双字母组合保存在1D单元阵列bigrams1中,并且来自文件的传入双字母组合将保存到另一个单元阵列words1中。让我们也假设它们中的某些值用于演示 -

bigrams1 = {
    'ar';
    'de';
    'c3';
    'd1';
    'ry';
    't1';
    'p1'}

words1 = {
    'de';
    'c3';
    'd1';
    'r9';
    'yy';
    'de';
    'ry';
    'de';
    'dd';
    'd1'}

现在,您可以使用此代码获取words1中存在的bigrams1的双字母组的计数 -

[~,~,ind] = unique(vertcat(bigrams1,words1));
bigrams_lb = ind(1:numel(bigrams1)); %// label bigrams1
words1_lb = ind(numel(bigrams1)+1:end);  %// label words1
counts = sum(bsxfun(@eq,bigrams_lb,words1_lb'),2)
out = [bigrams1 num2cell(counts)]

代码运行的输出是 -

out = 
    'ar'    [0]
    'de'    [3]
    'c3'    [1]
    'd1'    [2]
    'ry'    [1]
    't1'    [0]
    'p1'    [0]

结果显示 - ar中找不到所有可能的bigrams列表中的第一个元素words1;第二个元素dewords1中有三次出现,依此类推。

答案 2 :(得分:1)

这个答案会创建所有bigrams,文件中的加载会进行一些清理,然后使用uniquehistc的组合来计算行数

生成所有Bigrams

请注意这里的顺序非常重要,因为unique会对数组进行排序,这样就可以预先创建它,以便输出符合期望值;

[y,x] = ndgrid(['0':'9','a':'z']);
allBigrams = [x(:),y(:)];

阅读文件

这会删除大小写,然后拉出任何0-9或a-z字符,然后创建这些

的列向量
fileText = lower(fileread('d:\loremipsum.txt'));
cleanText = regexp(fileText,'([a-z0-9])','tokens');
cleanText = cell2mat(vertcat(cleanText{:}));

通过移动一个并连接

从文件创建双字节
fileBigrams = [cleanText(1:end-1),cleanText(2:end)];

获取计数

所有双字母组的集合被添加到我们的集合中(因此可以为所有可能的值创建值)。然后使用unique的第3个输出为每个唯一行分配值∈{1,2,...,1296}。然后使用histc创建计数,其中二进制位等于unique输出中的一组值,从每个二进制数中减去1以删除我们添加的完整集合双字母

[~,~,c] = unique([fileBigrams;allBigrams],'rows');
counts = histc(c,1:1296)-1;

显示

查看针对文字的计数

[allBigrams, counts+'0']

或可能更有用的东西......

[sortedCounts,sortInd] = sort(counts,'descend');
[allBigrams(sortInd,:), sortedCounts+'0']


ans =

or9
at8
re8
in7
ol7
te7
do6 ...

答案 3 :(得分:0)

没有查看整个代码片段,但是从问题顶部的示例中,我认为您正在寻找直方图:

string1 = 'ASHRAFF'
nr = histc(string1,'A':'Z')

会给你:

 2     0     0     0     0     2     0     1     0     0     0     0     0     0     0     0     0     1     1     0     0     0     0     0     0     0     0

(通过hist获得了可行的解决方案,但是@The Minion节目histc在这里更容易使用。)

请注意,此解决方案仅处理大写字母。

如果你想把小写字母放在正确的bin中,你可能想要这样做:

string1 = 'ASHRAFF'
nr = histc(upper(string1),'A':'Z')

或者如果您希望它们单独显示:

string1 = 'ASHRaFf'
nr = histc(upper(string1),['a':'z' 'A':'Z'])

答案 4 :(得分:0)

bi_freq1 = zeros(1,all_bigrams_len);
for k=1: vocab_len1
 for i=1:all_bigrams_len
  if  char(vocab1(k)) == char(bigrams(i))
       bi_freq1(i) = frequencies1(k);
  end
 end
end