Помогите мне ускорить этот код - Python - PullRequest
0 голосов
/ 14 апреля 2011

Ребята, я пишу эту программу, которая просматривает список твитов и возвращает слова, которые использовались чаще всего.

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

см. Код ниже

#import string
import re
from string import punctuation
from operator import itemgetter
import pprint


class Tweet:
    def __init__(self, timestamp, userId, message):
        self.timestamp = timestamp
        self.userId = userId
        self.message = message

    def getDate(self):
        tokens = re.split(' ',  self.timestamp)
        return tokens[0]

    def __repr__(self):
        return "[timestamp=%s userId=%s message=%s]" % (self.timestamp, self.userId, self.message)

outfile  = file 
def readOneTweet(file):

    """ Reads a single tweet from the file, and returns the string containing the tweet.
    This will often just be a single line from the file, but may be more if it ends with a slash.
    """
    lineBuffer = "" 
    while True:
        # TODO: read the line and strip it

        rawLine = file.readline().strip('\n')
        if (len(rawLine)== 0):
            break

        lineBuffer +=rawLine

        if (rawLine[(len(rawLine)-1)]!= "\\"):
            break
    return lineBuffer 



def readTweets():
    tweets = []
    inputfile = raw_input("Enter filename: ")

    # move the try / except around a single tweet.
    # so that we can keep going if we encounter a line with an error.
    try:
        f = open(inputfile , "r")

        while True:
            tweet = readOneTweet(f) # readOneTweet is method
            if not tweet:
                break
            try:
                lineStrip = tweet.rstrip()

                split_word = re.split('\t',  lineStrip.lower()) #('/([^a-z])([A-Z]) ([0-9])/n:.;\]+/', line.lower())

                tweetTime = split_word[1]
                userId = split_word[0]
                message = split_word[2]
                tweets.append(Tweet(tweetTime, userId, message))
                if len(tweets) % 10000 == 0:
                    print 'read', len(tweets), 'tweets'
            except IndexError, e:
                print "bad tweet", tweet
    except IOError: 
        print "file not found!"
    return tweets

######################DATA ##############
"""
- Need to separate tweets
- Obtain information about each tweet - UserID, Time, words
"""

def writeWordFile(word):
    toWrite = 'test.txt'
    fileHandle = open ( toWrite, 'w' )
    for i in word:
        fileHandle.write (i)

def dailyMessages(twt):
    dailyMsg =dict ()
    for i in twt:
        date =i.getDate()
        #print  i.message
        #dailyMsg[date] =messageList
        if dailyMsg.has_key(date):
            dailyMsg[date].append(twt)
        else:
            dailyMsg[date] =[twt]
    #for k, v in dailyMsg.items():
        #print k, v, '\n'
    return dailyMsg    

"""
Takes dailyTweets and perform  word coun. 
"""
def dailyWord(tweetsByDay):
    dailyTweetsWordCount = { }
    for date in tweetsByDay.keys():
        dayTweets =tweetsByDay[date]
        if len(dayTweets) != 0:
            count = wordCount(dayTweets)
            dailyTweetsWordCount[date] = count
    return dailyTweetsWordCount


def wordCount(tweets):
    """Takes a list of tweets and returns a dictionary of counts for words"""
    N = 100
    # we'll build a dictionary mapping each word to a SET of users who have used it
    wordTweeters = {}
    for tweet in tweets:
       # print tweet
        for i in tweet:
            for word in i.message.split():
                if not  wordTweeters.has_key(word):
                    wordTweeters[word] = set()
                wordTweeters[word].add(i.userId)

    # we'll build up a dictionary mapping each word to the number of users who have used it.
    p = dict ()
    #print wordTweeters
    for day in wordTweeters.keys():
        usersNo = len (wordTweeters[day])
        p[day] = usersNo
    #print wordTweeters

    return  p  #wordTweeters, p

def searchForMemes(tweetUserCounts):
    for  key in tweetsUserCounts.keys():
       # for pmeme in tweetUserCounts
       pass


    """Takes information returned by daily word"""


def isMeme(word, day1Count, day2Count, day3Count):

    #takes the daily count
    # check if it is a meme
    #First -  check count
        #check count in different days
        # determine the if it qualifies as a tweet
        # if not drop it  do not do below checks 
    #Second - time stamp
        #CHECK ITS TIME TRACK
        #How is the count of over time
        # rise and fall
        # 
    #Third - user id
        # check if is form different users
            #how many of those counts are from different users
       pass 

def dayUserCount(z,word, d1, d2, d3):
    """ assume dictionary will be input"""

    # check if the word exist in the dictionary

    if z.has_key(d1):
        date1 =z[d1]
        #print value.keys()
        if  date1.has_key(word):
            print date1
            c1 =date1[word]
        else:
            print "word not used in %s"%d1
            c1 =0
    else:
        print 'date does not exist'

    if z.has_key(d2):
        #print value.keys()
        date2 =z[d2]
        if  date2.has_key(word):
            print date2
            c2 =date2[word]
        else:
            print "word not used in %s"%d2
            c2 =0
    else:
        print 'date does not exist'

    if z.has_key(d3):
        date3 = z[d3]
        if date3.has_key(word):
            print date3
            c3 =date3[word]
        else:
            print "word not used in %s" %d3
            c3 =0
    else:
        print 'date does not exist'

    result = "Word: %s , %s count: %s, %s count: %s, %s count: %s"%(word,d1,c1,d2,c2, d3,c3)
    return result           



# supportive functions 
def hashtag(tw):
    hasht =[]
    for word in tw.split():
        if word.startswith('#'):
            hasht.append(word)
    return hasht


def httpTag(tw):
    http =[]
    for word in tw.split():
        if word.startswith('http'):
            http.append(word)
    return http

def reply(tw):
    reply =[]
    for word in tw.split():
        if word.startswith('@'):
            reply.append(word)
    return reply

def reTweet(tw):
    rt =[]
    for word in tw.split():
        if word.startswith('rt') or word.startswith('RT'):
            rt.append(word)
    return rt






"""
Old functions 
"""
def writeToFile(tweet):
    #filename = test.txt
    filek = open('test.txt', 'w')
    print "writing on the file: "
    filek.write(tweet)
   # print " _____--------______" + tweet
    filek.close()

# count word frequency.
def f2count():
    N = 100000000000
    words = {}
    words_gen = (word.strip(punctuation).lower()
                 for line in open('c.txt')
                        for word in line.split())
    for word in words_gen:
        words[word] = words.get(word, 0) + 1

    top_words = sorted(words.iteritems(),
                   key=lambda(word, count): (-count, word))[:N] 

    for word, frequency in top_words:
        print "%s: %d" % (word, frequency)

Ответы [ 3 ]

7 голосов
/ 14 апреля 2011
if (len(rawline) == 0):

можно записать как

if rawline:

Никогда не следует использовать len(rawline) - 1 в качестве индекса, просто используйте rawline[-1].

Я не знаю, почему вы используетеre.split(), когда вы можете просто сделать linestip.lower().split('\t').

Не используйте dailyMsg.has_key(date), используйте date in dailyMsg.

Когда вы перебираете tweetsByDay, вы действительно должны бытьвыполняя это:

for date, value in tweetsByDay.items():`

таким образом, вам не нужно вручную связывать значение с ключом.

Это только начало.Есть еще много вопросов, которые нужно проработать.Я думаю, что вам действительно нужно поработать над освоением Python - из чтения вашего кода становится ясно, что либо Python не является вашим родным языком, либо вы узнали из ресурса, который не научил вас правильно его писать.Например, почему вы ставите круглые скобки вокруг условных выражений?Это не обязательно в Python (хотя это артефакт из Algol-подобных языков, таких как C или Java).Почему вы используете dict() вместо {}?Желательно писать пустой диктовку вторым способом. этот урок по идиоматическому Python может оказаться полезным.

1 голос
/ 14 апреля 2011

wordCount() может работать параллельно.Поскольку каждый твит напрямую не зависит от другого, нет причин для последовательного просмотра списка.Разбейте список твитов на более мелкие списки, а затем создайте поток для каждого подсписка.Как только все они закончат создание своих под-словарей, вы можете немного поработать, чтобы объединить их все в один словарь.

РЕДАКТИРОВАТЬ:
Пример того, как парализовать суммирование списка,Вы бы изменили тело потока, чтобы выполнить любую задачу.

from threading import Thread

numbers = range(1000)

class Sum(Thread):
  def __init__(self, numList):
    Thread.__init__(self)
    self.numList = numList
    self.total = 0

  def run(self):
    for num in self.numList:
      self.total += num

numThreads = 7
threads = []
perThread = len(numbers)/numThreads
for i in xrange(numThreads):
  start = i*perThread
  t = Sum(numbers[start:len(numbers) if i == numThreads-1 else start+perThread])
  t.start()
  threads.append(t)

grandTotal = 0
for t in threads:
  t.join()
  grandTotal += t.total

print grandTotal
0 голосов
/ 16 апреля 2011

Этот код полон неоптимизированных фрагментов.

Например, каждый вызов функции занимает время.Не делайте бесполезных вызовов для работы, и вы сэкономите время.Некоторые вызовы можно заменить списком понимания: хэштег, httpTag, ... и т. Д.

Я мог бы помочь оптимизировать, но:

1 - в настоящее время у меня недостаточно времени для продолжительной работытакого рода

2 - мы не можем оптимизировать, потому что код не завершен: где вызываются следующие функции?:

readTweets
writeWordFile
dailyMessages
dailyWord
wordCount
searchForMemes
isMeme
dayUserCount
hashtag
httpTag
reply
reTweet
writeToFile
f2count

3 - Я устал отвечать на новые зарегистрированные люди, которые появляются в стеке с тяжелыми вопросами и исчезают после этого, иногда не давая никаких новостей или комментариев.Извините, если вы намеревались этого не делать

РЕДАКТИРОВАТЬ

writeToFile

f2count

, очевидно, должны быть удалены из списка.

...