【问题标题】:Forming Bigrams of words in list of sentences with Python用 Python 在句子列表中形成单词的 Bigrams
【发布时间】:2014-03-17 15:53:12
【问题描述】:

我有一个句子列表:

text = ['cant railway station','citadel hotel',' police stn']. 

我需要形成二元对并将它们存储在一个变量中。问题是当我这样做时,我得到的是一对句子而不是单词。这是我所做的:

text2 = [[word for word in line.split()] for line in text]
bigrams = nltk.bigrams(text2)
print(bigrams)

产生

[(['cant', 'railway', 'station'], ['citadel', 'hotel']), (['citadel', 'hotel'], ['police', 'stn'])

火车站和城堡酒店不能形成一个二元组。我想要的是

[([cant],[railway]),([railway],[station]),([citadel,hotel]), and so on...

第一句的最后一个词不能和第二句的第一个词合并。 我应该怎么做才能让它发挥作用?

【问题讨论】:

    标签: python list list-comprehension nltk collocation


    【解决方案1】:

    使用list comprehensionszip

    >>> text = ["this is a sentence", "so is this one"]
    >>> bigrams = [b for l in text for b in zip(l.split(" ")[:-1], l.split(" ")[1:])]
    >>> print(bigrams)
    [('this', 'is'), ('is', 'a'), ('a', 'sentence'), ('so', 'is'), ('is', 'this'), ('this',     
    'one')]
    

    【讨论】:

    • 如果你想将每个句子的二元组保留在自己的列表中:[[b for b in zip(l.split(" ")[:-(n-1)], l.split(" ")[(n-1):])] for l in x]
    • 这对于一般情况来说是一种很好的方法,可以直接解决 OP 的问题,但也值得一提的是,有时将标点符号视为单独的单词很有用,例如如果目的是训练一个 n-gram 语言模型,为了计算一个句子的语法性,那么 .split(" ") 在这里可能不是理想的。最好将 nltk.word_tokenize 与 nltk.sent_tokenize 一起使用
    【解决方案2】:
    from nltk import word_tokenize 
    from nltk.util import ngrams
    
    
    text = ['cant railway station', 'citadel hotel', 'police stn']
    for line in text:
        token = nltk.word_tokenize(line)
        bigram = list(ngrams(token, 2)) 
    
        # the '2' represents bigram...you can change it to get ngrams with different size
    

    【讨论】:

      【解决方案3】:

      与其将文本转换为字符串列表,不如将每个句子单独作为一个字符串开始。我还删除了标点符号和停用词,如果与您无关,请删除这些部分:

      import nltk
      from nltk.corpus import stopwords
      from nltk.stem import PorterStemmer
      from nltk.tokenize import WordPunctTokenizer
      from nltk.collocations import BigramCollocationFinder
      from nltk.metrics import BigramAssocMeasures
      
      def get_bigrams(myString):
          tokenizer = WordPunctTokenizer()
          tokens = tokenizer.tokenize(myString)
          stemmer = PorterStemmer()
          bigram_finder = BigramCollocationFinder.from_words(tokens)
          bigrams = bigram_finder.nbest(BigramAssocMeasures.chi_sq, 500)
      
          for bigram_tuple in bigrams:
              x = "%s %s" % bigram_tuple
              tokens.append(x)
      
          result = [' '.join([stemmer.stem(w).lower() for w in x.split()]) for x in tokens if x.lower() not in stopwords.words('english') and len(x) > 8]
          return result
      

      要使用它,请这样做:

      for line in sentence:
          features = get_bigrams(line)
          # train set here
      

      请注意,这更进一步,实际上是对二元组进行统计评分(这将在训练模型时派上用场)。

      【讨论】:

      • stemmerapple 更改为appl 所以我得到['appl basket']
      • 是的,Porter 词干分析器有一些限制。
      • 但这不是句子,你应该使用from_documents
      【解决方案4】:

      没有 nltk:

      ans = []
      text = ['cant railway station','citadel hotel',' police stn']
      for line in text:
          arr = line.split()
          for i in range(len(arr)-1):
              ans.append([[arr[i]], [arr[i+1]]])
      
      
      print(ans) #prints: [[['cant'], ['railway']], [['railway'], ['station']], [['citadel'], ['hotel']], [['police'], ['stn']]]
      

      【讨论】:

      • 默认情况下它们是二元组吗?因为我需要它们来正确拼写。
      • @Sword 您可以看到它仅从最后一行(打印之前)生成二元组。玩它,尝试不同的句子,自己看看;)
      【解决方案5】:
      >>> text = ['cant railway station','citadel hotel',' police stn']
      >>> bigrams = [(ele, tex.split()[i+1]) for tex in text  for i,ele in enumerate(tex.split()) if i < len(tex.split())-1]
      >>> bigrams
      [('cant', 'railway'), ('railway', 'station'), ('citadel', 'hotel'), ('police', 'stn')]
      

      使用枚举和拆分函数。

      【讨论】:

        【解决方案6】:

        读取数据集

        df = pd.read_csv('dataset.csv', skiprows = 6, index_col = "No")
        

        收集所有可用月份

        df["Month"] = df["Date(ET)"].apply(lambda x : x.split('/')[0])
        

        每月为所有推文创建令牌

        tokens = df.groupby("Month")["Contents"].sum().apply(lambda x : x.split(' '))
        

        每月创建二元组

        bigrams = tokens.apply(lambda x : list(nk.ngrams(x, 2)))
        

        每月计算二元组

        count_bigrams = bigrams.apply(lambda x : list(x.count(item) for item in x))
        

        用整洁的数据框整理结果

        month1 = pd.DataFrame(data = count_bigrams[0], index= bigrams[0], columns= ["Count"])
        month2 = pd.DataFrame(data = count_bigrams[1], index= bigrams[1], columns= ["Count"])
        

        【讨论】:

          【解决方案7】:

          只是修复 Dan 的代码:

          def get_bigrams(myString):
              tokenizer = WordPunctTokenizer()
              tokens = tokenizer.tokenize(myString)
              stemmer = PorterStemmer()
              bigram_finder = BigramCollocationFinder.from_words(tokens)
              bigrams = bigram_finder.nbest(BigramAssocMeasures.chi_sq, 500)
          
              for bigram_tuple in bigrams:
                  x = "%s %s" % bigram_tuple
                  tokens.append(x)
          
              result = [' '.join([stemmer.stem(w).lower() for w in x.split()]) for x in tokens if x.lower() not in stopwords.words('english') and len(x) > 8]
              return result
          

          【讨论】:

            【解决方案8】:

            最好的方法是使用“zip”函数来生成n-gram。 其中 2 in range 函数是克数

            test = [1,2,3,4,5,6,7,8,9]
            print(test[0:])
            print(test[1:])
            print(list(zip(test[0:],test[1:])))
            %timeit list(zip(*[test[i:] for i in range(2)]))
            

            o/p:

            [1, 2, 3, 4, 5, 6, 7, 8, 9]  
            [2, 3, 4, 5, 6, 7, 8, 9]  
            [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (7, 8), (8, 9)]  
            1000000 loops, best of 3: 1.34 µs per loop  
            

            【讨论】:

              【解决方案9】:

              有很多方法可以解决,但我是这样解决的:

              >>text = ['cant railway station','citadel hotel',' police stn']
              >>text2 = [[word for word in line.split()] for line in text]
              >>text2
              [['cant', 'railway', 'station'], ['citadel', 'hotel'], ['police', 'stn']]
              >>output = []
              >>for i in range(len(text2)):
                  output = output+list(bigrams(text2[i]))
              >>#Here you can use list comphrension also
              >>output
              [('cant', 'railway'), ('railway', 'station'), ('citadel', 'hotel'), ('police', 'stn')]
              

              【讨论】:

                【解决方案10】:

                我认为最好和最通用的方法如下:

                n      = 2
                ngrams = []
                
                for l in L:
                    for i in range(n,len(l)+1):
                        ngrams.append(l[i-n:i])
                

                或者换句话说:

                ngrams = [ l[i-n:i] for l in L for i in range(n,len(l)+1) ]
                

                这应该适用于任何n 和任何序列l。如果没有长度为 n 的 ngram,则返回空列表。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 2014-02-17
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-10-09
                  • 2020-05-23
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多