Applying a function to a DataFrame column returns NoneType
<p>I have a DataFrame with source IP addresses and I want to check if they belong to a documented CIDR range. </p>

<pre><code>netflow_df2["sip"].head(10)

timestamp
2016-10-04 16:24:58    40.101.X.X
2016-10-04 16:24:58    40.101.X.X
2016-10-04 16:24:58     40.101.X.X
2016-10-04 16:24:58     67.X.X.X
2016-10-04 16:24:58        10.1.1.X
2016-10-04 16:24:58      10.1.Y.Y



import ipaddress
import numpy
from collections import defaultdict
from pandas.util.testing import test_parallel
</code></pre>

<p>I put all the documented CIDRs I know of in a dict:</p>

<pre><code># dict to key (vlan, designation)
nets = defaultdict(str)
nets["10.1.0.0/24"] = "13, web"
net["10.2.0.0/24"] = "14, department X"
net["10.3.55.0/24"] = "601, wifi"
...
net["10.1.243.0/24"] = "1337, IT"
</code></pre>

<p>I define my function:</p>

<pre><code>def netmap(ip, network_lookup_dict):
    for key, value in network_lookup_dict.iteritems() :
        if ipaddress.ip_address(unicode(ip)) in ipaddress.ip_network(unicode(key)):
            return value
            # print "VLAN: " + infos[0].strip() + ", Network designation: " + infos[1].strip()
        else:
            return numpy.NAN
</code></pre>

<p>And now I map it:</p>

<pre><code>@test_parallel(num_threads=4)
def apply_netmap(netflow_df2, location="ABC"):
    % time netflow_df2["sip_infos"] = netflow_df2["sip"].map(lambda ip: netmap(ip, nets))
    return netflow_df2


CPU times: user 3min 14s, sys: 21.2 s, total: 3min 36s
Wall time: 3min 5s


netflow_df3 = apply_netmap(netflow_df2)
</code></pre>

<p>My error is:</p>

<pre><code>netflow_df3.head(10)
</code></pre>

<blockquote>
  <p>AttributeError: 'NoneType' object has no attribute 'head'</p>
</blockquote>

<p>I was under the impression this function would map the return value of <code>netmap()</code> to the DataFrame column. That is the reason why I also return <code>NAN</code>. This does not appear to be the case. Also it's super slow.</p>

<p>The problem is that I use the <code>defaultdict</code> in the <code>netmap</code> function wrong. This yields the corrects results:</p>

<pre><code>def netmap(ip, network_lookup_dict):
    for key, value in network_lookup_dict.iteritems(): 
        try:
            if ipaddress.ip_address(unicode(ip)) in ipaddress.ip_network(unicode(key)):
                return network_lookup_dict.get(key)
        except KeyError:
            print "duh"
            return numpy.NaN
</code></pre>

<p>The <code>return</code> statement was broken. It's confusing to me why this would corrupt the <code>DataFrame</code> object, but I suppose everything has bugs.</p>

python pandas networking