2

У меня есть набор файлов из example001.txt в example100.txt . Каждый файл содержит список ключевых слов из расширенного набора (расширенный набор доступен, если мы этого хотим).

Таким образом, example001.txt может содержать

apple
banana
...
otherfruit

Я хотел бы иметь возможность обрабатывать эти файлы и создавать что-то похожее на матрицу, поэтому в верхней строке есть список examples* , фрукты внизу и «1» в столбце, если фрукты находятся в файл.

Примером может быть ...

x           example1    example2   example3
Apple         1            1          0
Babana        0            1          0
Coconut       0            1          1

Любая идея, как я мог бы создать какую-то магию командной строки, чтобы собрать это вместе? Я на OSX и счастлив с Perl или Python ...

4 ответа4

4

С Python вы можете установить textmining через

sudo pip install textmining

Затем создайте новый файл - назовем его matrix.py и добавим следующее:

#!/usr/bin/env python
import textmining
import glob

tdm = textmining.TermDocumentMatrix()

files = glob.glob("/Users/foo/files/*.txt")
print(files)
for f in files:
  content = open(f).read()
  content = content.replace('\n', ' ')
  tdm.add_doc(content)
tdm.write_csv('matrix.csv', cutoff=1)

Сохраните его и вызовите chmod +x matrix.py . Теперь просто запустите его с помощью ./matrix.py . Эта программа будет искать в каталоге, указанном в glob() и записывать выходную матрицу в matrix.csv в вашем текущем каталоге, возможно, так:

Как видите, единственным недостатком является то, что он не выводит имена документов. Мы можем добавить этот список, используя пару команд bash - нам нужен только список имен файлов:

echo "" > files.txt; find /Users/foo/files/ -type f -iname "*.txt" >> files.txt

И затем вставьте это вместе с matrix.csv:

paste -d , files.txt matrix.csv > matrix2.csv 

Вуаля, наша полная матрица терм-документов:

Я мог бы представить, что есть менее запутанные решения, но это Python, и я не знаю его достаточно хорошо, чтобы изменить код для вывода всей правильной матрицы.

2

Это почти что решение. Я просто добавил в скрипт Python команды bash, выполняемые через os.sytem, чтобы поместить все в один скрипт python без необходимости переключения между python и консолью bash.

#!/usr/bin/env python
import textmining
import glob
import os
tdm = textmining.TermDocumentMatrix()
files = glob.glob("/Users/andi/Desktop/python_nltk/dane/*.txt")
os.system("""echo "" > files.txt; find /Users/andi/Desktop/python_nltk/dane -type f -iname "*.txt" >> files.txt""")
print(files)
for f in files:
  content = open(f).read()
  content = content.replace('\n', ' ')
  tdm.add_doc(content)
tdm.write_csv('matrix.csv', cutoff=1)

os.system("""paste -d , files.txt matrix.csv > matrix2.csv """)
1

Я не могу дать вам что-то столь же красивое, как решение на python от slhck, но вот чисто bash:

printf "\t" && 
for file in ex*; do \
  printf "%-15s" "$file "; 
done &&
echo "" && 
while read fruit; do \
    printf "$fruit\t";
    for file in ex*; do \
      printf "%-15s" `grep -wc $fruit $file`;  
    done;  
echo ""; 
done < superset.txt

Если вы скопируете / вставите эту ужасную вещь в терминал, предполагая, что ваш список фруктов находится в файле с именем superset.txt одному фрукту в строке, вы получите:

        example1       example2       example3       
apple   1              2              2              
banana  1              1              2              
mango   0              1              1              
orange  1              1              2              
pear    0              1              1              
plum    0              0              1              

ОБЪЯСНЕНИЕ:

  • printf "\t" : распечатать TAB, чтобы имена файлов были выровнены по концу названий фруктов.
  • for file in ex*; [...] done : напечатать имена файлов (при условии, что они являются единственными файлами, имя которых начинается с ex .
  • echo "" : напечатать новую строку
  • while read fruit; do [...]; done <list : list должен быть текстовым файлом, содержащим упомянутое вами надмножество, т.е. все фрукты, по одному фрукту в строке. Этот файл читается в этом цикле, и каждый фрукт сохраняется как $fruit .
  • printf "$fruit\t"; : напечатайте название плода и табуляцию.
  • for file in ex*; do [...]; done : здесь мы снова просматриваем каждый файл и используем grep -wc $fruit $file чтобы узнать, сколько раз в этом файле находился фрукт, который мы сейчас обрабатываем.

Вы также можете использовать column но я никогда не пытался:

 The column utility formats its input into multiple columns.
 Rows are filled before columns.  Input is taken from file oper‐
 ands, or, by default, from the standard input.  Empty lines are
 ignored unless the -e option is used.

А вот и Perl. Технически, это один лайнер, хотя и длинный:

perl -e 'foreach $file (@ARGV){open(F,"$file"); while(<F>){chomp; $fruits{$_}{$file}++}} print "\t";foreach(sort @ARGV){printf("%-15s",$_)}; print "\n"; foreach $fruit (sort keys(%fruits)){print "$fruit\t"; do {$fruits{$fruit}{$_}||=0; printf("%-15s",$fruits{$fruit}{$_})} for @ARGV; print "\n";}' ex*

Вот он в форме комментария сценария, который на самом деле может быть понятным:

#!/usr/bin/env perl
foreach $file (@ARGV){ ## cycle through the files
    open(F,"$file");
    while(<F>){
    chomp;## remove newlines
    ## Count the fruit. This is a hash of hashes
    ## where the fruit is the first key and the file
    ## the second. For each fruit then, we will end up
    ## with something like this: $fruits{apple}{example1}=1
    $fruits{$_}{$file}++; 
    }
}
print "\t"; ## pretty formatting

## Print each of the file names
foreach(sort @ARGV){
    printf("%-15s",$_)
}
print "\n";  ## pretty formatting

## Now, cycle through each of the "fruit" we 
## found when reading the files and print its
## count in each file.
foreach $fruit (sort keys(%fruits)){
    print "$fruit\t"; ## print the fruit names
    do {
        $fruits{$fruit}{$_}||=0; ## Count should be 0 if none were found
        printf("%-15s",$fruits{$fruit}{$_}) ## print the value for each fruit
    } for @ARGV;
    print "\n"; ## pretty formatting
} 

Это дает преимущество совладания с произвольными "фруктами", а не суперсет. Кроме того, оба эти решения используют собственные инструменты * nix и не требуют установки дополнительных пакетов. Тем не менее, решение python в ответе slhck является более лаконичным и дает более приятный вывод.

0

В Python вы можете использовать sklearn.feature_extraction.text.CountVectorizer.fit_transform: он изучает словарь словаря и возвращает матрицу терминологического документа.

Пример:

import sklearn
import sklearn.feature_extraction

vectorizer = sklearn.feature_extraction.text.CountVectorizer(min_df=1)

corpus = ['This is the first document.',
        'This is the second second document.',
        'And the third one.',
        'Is this the first document? This is right.',]

X = vectorizer.fit_transform(corpus).toarray()
print('X: {0}'.format(X))
print('vectorizer.vocabulary_: {0}'.format(vectorizer.vocabulary_))

выходы:

X: [[0 1 1 1 0 0 0 1 0 1]
    [0 1 0 1 0 0 2 1 0 1]
    [1 0 0 0 1 0 0 1 1 0]
    [0 1 1 2 0 1 0 1 0 2]]

vectorizer.vocabulary_: {u'and': 0, u'right': 5, u'third': 8, u'this': 9, u'is': 3,
                         u'one': 4, u'second': 6, u'the': 7, u'document': 1, u'first': 2}

Поскольку вы работаете с файлами, вас может заинтересовать метод sklearn.feature_extraction.text.CountVectorizer.transform() также.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .