Question

How do I optimize searching two tuples of tuples for large tsv file in python?

Hello. I am a python newb, and have been working on searching for matching tuple elements using two seperate tuples. I am using files that have up to 3M lines and what I have come up with is very slow. I have been reading posts for weeks, but do not seem to piece code together correctly. This is what I have so far. (data has been edited and simplified for clarity). Say for instance, I have:

authList = (jennifer, 35, 20),(john, 20, 34), (fred, 34, 89)  # this is a tuple of
#unique tweet authors with their x, y coordinates exported from MS Access in the form
#of a txt file.

rtAuthors = (larry, 57, 24, simon), (jeremy, 24, 15, john), (sandra, 39, 24, fred) 
# this is a tuple of tuples including the author, their x,y coordinates, and the
#author whom they are retweeting (taken from the "RT @ portion of their tweet)

I am attempting to create a new tuple (rtAuthList) that pulls the x, y coordinates from authList for any retweeted author in rtAuthors.

So I would have a new tuple that would be something like this:

 rtAuthList = (jeremy, 24, 15, john, 20, 34),(sandra, 39, 24, fred, 34, 89)

I really have two parts to my question so I am not sure if I should post two questions or retitle my question to include both. First of all, this process takes about an hour to run the way I've written it. There must be a faster way.

The other part of my question is why is it only completing about half of the final tuple? With my current dataset, I have about 250,000 lines in authList, and 500,000 lines in rtAuthors after these two steps. But when I process the third step and open the rtAuthList at the end, it has only looked at the first 10 days of my data, ignoring the last 20 --I have a month of tweets that I am working with). I'm not sure why it is not checking through the entire rtAuthors list.

I am including my entire code below so that you understand what I'm trying to do, but I am really asking for help with step 3, following my creation of the authList and rtAuthors tuples. And please understand I am new to programming completely so write answers as though I dont know anything, although that is probably obvious when you look at my code.

import csv
import sys
import os

authors= ""

class TwitterFields:             ### associated with monthly tweets from Twitter API
    def __init__(self, ID, COORD1, COORD2,TIME, AUTH, TEXT): 
        self.ID = ID
        self.COORD1 = COORD1
        self.COORD2 = COORD2
        self.TIME = TIME
        self.AUTH=AUTH
        self.TEXT=TEXT
        self.RTAUTH=""
        self.RTX=""
        self.RTY=""

        description="Twitter Data Class: holds twitter data fields from API "
        author=""

class AuthorFields:             ## associated with the txt file exported from MS Access
    def __init__(self, AUTH, COORD1, COORD2):
        self.AUTH=AUTH
        self.COORD1 = COORD1
        self.COORD2 = COORD2
        self.RTAUTH=""
        self.RTX=""
        self.RTY=""

        description="Author Data Class: holds author data fields from MS Access export"
        author=""


tw = [] #empty list to hold data from class TwitterFields
rt = [] #empty list to hold data from class AuthorFields


authList = ()        ## tuple for holding auth, x, and y from tw list
rtAuthors = ()      ## tuple for holding tuples from rt where "RT @" is in tweet text
rtAuthList =()      ## tuple for holding results of set intersection 

e = ()                  # tuple for authList
b=()                    # tuple for rtAuthors
c=()                    # tuple for rtAuthList
bad_data = []      #A container for bad data 

with open(r'C:\Users\Amy\Desktop\Code\Merge2.txt') as g:   #open MS Access export file
    for line in g:                                             
        strLine = line.rstrip('\r\n').split("\t")
        tw.append(AuthorFields( str(strLine[0]),   #reads author name       
                                 strLine[1],       # x coordinate
                                 strLine[2]))      # y coordinate


## Step 1 ##
# Loop through the unique author dataset (tw) and make a list of all authors,x, y
try:
    for i in range(1, len(tw)): 
                e=((tw[i].AUTH[:tw[i].AUTH.index(" (")], tw[i].COORD1,tw[i].COORD2))
                authList = authList +(e,)
except:
    bad_data.append(i)

print "length of authList = ", len(authList)    


# Loop through tweet txt file from MS Access 

with open(r'C:\Users\Amy\Desktop\Code\Syria_2012_08UTCedits3.txt') as f:
    for line in f:
        strLine=line.rstrip('\r\n').split('\t') # parse each line for tab spaces
        rt.append(TwitterFields(str(strLine[0]) ,      #reads tweet ID              
                              strLine[5],                         # x coordinate
                              strLine[6],                         # y coordinate
                              strLine[8],                         # time stamp
                              strLine[9],                         # author
                              strLine[12] ))                    # tweet text

## Step 2 ##
## Loop through new list (rt) to find all instances of "RT @" and retrieve author name

for i in range(1, len(rt)):        # creates tuple of (authors, x, y, rtauth, rtx, rty)
    if (rt[i].TEXT[:4] == 'RT @'): # finds author in tweet text between "RT @" and ":"
            end = rt[i].TEXT.find(":")
            rt[i].RTAUTH=rt[i].TEXT[4:end]
            b = ((rt[i].AUTH, rt[i].COORD1, rt[i].COORD2, rt[i].TIME, rt[i].RTAUTH))
            rtAuthors = rtAuthors + (b,)
    else:
        pass

print "length of rtAuthors = ", len(rtAuthors)


## Step 3 ##

## Loop through new rtAuthors tuple and find where rt[i].RTAUTH matches tw[i].AUTH in
## authList.


set1 = set(k[4] for k in rtAuthors).intersection(x[0] for x in authList)
#e = iter(set1).next()
set2 = list(set1)


print "Length of first set = ", len(set2)

# For each match, grab the x and y from authList and copy to rt[i].RTX and rt[i].RTY

for i in range(1, len(rtAuthors)):
    if rt[i].RTAUTH in set2:
        authListIndex = [x[0] for x in authList].index(rt[i].RTAUTH) #get record # 
        rt[i].RTX= authList[authListIndex][1] # grab the x 
        rt[i].RTY = authList[authListIndex][2] # grab the y
        c = ((rt[i].AUTH, rt[i].COORD1, rt[i].COORD2, rt[i].TIME, rt[i].RTAUTH,
        rt[i].RTX, rt[i].RTY))
        rtAuthList = rtAuthList + (c,)   # create new tuple of tuples with matches

else:
    pass

print "length of rtAuthList = ", len(rtAuthList)
Was it helpful?

Solution

In step 3 you're using an O(n²) algorithm to match up the tuples. If you build a lookup dictionary for authList, you can do it in O(n) instead...

>>> authList = ('jennifer', 35, 20), ('john', 20, 34), ('fred', 34, 89)
>>> rtAuthors = ('larry', 57, 24, 'simon'), ('jeremy', 24, 15, 'john'), ('sandra', 39, 24, 'fred')
>>> authDict = {t[0]: t[1:] for t in authList}
>>> rtAuthList = [t + authDict[t[-1]] for t in rtAuthors if t[-1] in authDict]
>>> print rtAuthList
[('jeremy', 24, 15, 'john', 20, 34), ('sandra', 39, 24, 'fred', 34, 89)]
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top