**Example data can be downloaded below.**

I am working on a project which crunches plain text files (`.lst`).

The name of the file names (`fileName`) are important because I'll extract `node` (e.g. `abessijn`) and `component` (e.g. `WR-P-E-A`) from them into a dataframe. Examples:

    abessijn.WR-P-E-A.lst
    A-bom.WR-P-E-A.lst
    acroniem.WR-P-E-C.lst
    acroniem.WR-P-E-G.lst
    adapter.WR-P-E-A.lst
    adapter.WR-P-E-C.lst
    adapter.WR-P-E-G.lst

Each file consists of one or more line. Each line consists of a sentence (inside `<sentence>` tags). Example (`abessijn.WR-P-E-A.lst`)

    <sentence>Vooral mijn abessijn ruikt heerlijk kruidig .. : ) )</sentence>
    <sentence>Mijn abessijn denkt daar heel anders over .. : ) ) Maar mijn kinderen richt ik ook niet af , zit niet in mijn bloed .</sentence>

From each line I extract the sentence, do some small modifications to it, and call it `sentence`. Up next is an element called `leftContext`, which takes the first part of the split between `node` (e.g. `abessijn`) and the sentence it came from. Finally, from `leftContext` I get `precedingWord`, which is the word preceding `node` in `sentence`, or the right most word in `leftContext` (with some limitations such as the option of a compound formed with a hyphen). Example:

    ID | filename             | node | component | precedingWord      | leftContext                               |  sentence
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    1    adapter.WR-P-P-F.lst  adapter  WR-P-P-F   aanpassingseenheid  Een aanpassingseenheid (                      Een aanpassingseenheid ( adapter ) , 
    2    adapter.WR-P-P-F.lst  adapter  WR-P-P-F   toestel             Het toestel (                                 Het toestel ( adapter ) draagt zorg voor de overbrenging van gegevens
    3    adapter.WR-P-P-F.lst  adapter  WR-P-P-F   de                  de aansluiting tussen de sensor en de         de aansluiting tussen de sensor en de adapter , 
    4    airbag.WS-U-E-A.lst   airbag   WS-U-E-A   den                 ja voor den                                   ja voor den airbag op te pompen eh :p
    5    airbag.WS-U-E-A.lst   airbag   WS-U-E-A   ne                  Dobby , als ze valt heeft ze dan wel al ne    Dobby , als ze valt heeft ze dan wel al ne airbag hee

That dataframe is exported as `dataset.csv`.

After that, the intention of my project comes at hand: I create a frequency table that takes `node` and `precedingWord` into account. From a variable I define `neuter` and `non_neuter`, e.g (in Python)

    neuter = ["het", "Het"]
    non_neuter = ["de","De"]

and a rest category `unspecified`. When `precedingWord` is an item from the list, assign it to the variable. Example of a frequency table output:

    node    |   neuter   | nonNeuter   | unspecified
    -------------------------------------------------
    A-bom       0          4             2
    acroniem    3          0             2
    act         3          2             1

The frequency list is exported as `frequencies.csv`.

I came up with the following script ([paste][2]) to do that.

    import os, pandas as pd, numpy as np, regex as re
    
    from glob import glob
    from datetime import datetime
    from html import unescape
    
    start_time = datetime.now()
    
    # Create empty dataframe with correct column names
    columnNames = ["fileName", "component", "precedingWord", "node", "leftContext", "sentence" ]
    df = pd.DataFrame(data=np.zeros((0,len(columnNames))), columns=columnNames)
    
    # Create correct path where to fetch files
    subdir = "rawdata"
    path = os.path.abspath(os.path.join(os.getcwd(), os.pardir, subdir))
    
    # "Cache" regex
    # See http://stackoverflow.com/q/452104/1150683
    p_filename = re.compile(r"[./\\]")
    
    p_sentence = re.compile(r"<sentence>(.*?)</sentence>")
    p_typography = re.compile(r" (?:(?=[.,:;?!) ])|(?<=\( ))")
    p_non_graph = re.compile(r"[^\x21-\x7E\s]")
    p_quote = re.compile(r"\"")
    p_ellipsis = re.compile(r"\.{3}(?=[^ ])")
    
    p_last_word = re.compile(r"^.*\b(?<!-)(\w+(?:-\w+)*)[^\w]*$", re.U)
    
    # Loop files in folder
    for file in glob(path+"\\*.lst"):
        with open(file, encoding="utf-8") as f:
            [n, c] = p_filename.split(file.lower())[-3:-1]
            fn = ".".join([n, c])
            for line in f:
                s = p_sentence.search(unescape(line)).group(1)
                s = s.lower()
                s = p_typography.sub("", s)
                s = p_non_graph.sub("", s)
                s = p_quote.sub("'", s)
                s = p_ellipsis.sub("... ", s)
    
                if n in re.split(r"[ :?.,]", s):
                    lc = re.split(r"(^| )" + n + "( |[!\",.:;?})\]])", s)[0]
        
                    pw = p_last_word.sub("\\1", lc)
        
                    df = df.append([dict(fileName=fn, component=c, 
                                       precedingWord=pw, node=n, 
                                       leftContext=lc, sentence=s)])
                continue
    
    # Reset indices
    df.reset_index(drop=True, inplace=True)
    
    # Export dataset
    df.to_csv("dataset/py-dataset.csv", sep="\t", encoding="utf-8")
    
    # Let's make a frequency list
    # Create new dataframe
    
    # Define neuter and non_neuter
    neuter = ["het"]
    non_neuter = ["de"]
    
    # Create crosstab
    df.loc[df.precedingWord.isin(neuter), "gender"] = "neuter"
    df.loc[df.precedingWord.isin(non_neuter), "gender"] = "non_neuter"
    df.loc[df.precedingWord.isin(neuter + non_neuter)==0, "gender"] = "rest"
    
    freqDf = pd.crosstab(df.node, df.gender)
    
    freqDf.to_csv("dataset/py-frequencies.csv", sep="\t", encoding="utf-8")
    
    # How long has the script been running?
    time_difference = datetime.now() - start_time
    print("Time difference of", time_difference)

*I'm running Python in 32 bit, because I'd like to use the [nltk module][3] in the future and they discourage users to use 64 bit.*

Seeing that the goal of Python was to make everything go smoothly, I was confused. **The goal is to beat a similar R script in execution speed.** I read Python was fast, so where did I go wrong? A colleague advised me to use Python which might be a faster case. I know you can't simply compare two languages that way, each has its merits. But in this specific case it seemed to me that Python ought to be faster in data crunching. My current Python code works, so there's no issue with `lower()` for me. Please tell me if I'm completely wrong. If someone could help me use some higher hierarchy functions as proposed on SO (imap, ifilter...) **and explaining them** that would be great.

What is the problem? Is Python slower in reading files and lines, or in doing regexes? Or is R simply better equipped to dealing with dataframes and can't it be beaten by pandas? *Or* is my code simply badly optimised and should Python indeed be the victor?

You can download the test data I used [*here*][4].

I'm a bit of a beginner, so please take the time to explain how they work and/or why they're better.

  [1]: http://pastebin.com/gtCrAdMq
  [2]: http://pastebin.com/rPFJKuBV
  [3]: http://www.nltk.org/
  [4]: http://bramvanroy.be/files/testdata.zip