Python Pandas df.ix not performing as expected
<p>Here is my function:</p>

<pre><code> def clean_zipcodes(df):
    df.ix[df['workCountryCode'].str.contains('USA') &amp; \
    df['workZipcode'].astype(str).str.len() &gt; 5, 'workZipcode'] = \
    df['workZipcode'].astype(int).floordiv(10000)


df.ix[df['contractCountryCode'].str.contains('USA') &amp; \
    df['contractZipcode'].astype(str).str.len() &gt; 5, 'contractZipcode'] = \
    df['contractZipcode'].astype(int).floordiv(10000)

return df
</code></pre>

<p>Here is my test function of what I expect:</p>

<pre><code>def test_clean_zipcodes():
testDf = pandas.DataFrame({'unique_transaction_id'  : ['1', '1', '1'],
                           'workZipcode'            : [838431000, 991631000, 99163],
                           'contractZipcode'        : [838431000, 991631000, 99163],
                           'workCountryCode'        : ['USA: STUFF', 'NONE: STUFF', 'USA: STUFF'],
                           'contractCountryCode'    : ['USA: STUFF', 'NONE: STUFF', 'USA: STUFF']})

resultDf = pandas.DataFrame({'unique_transaction_id'    : ['1', '1', '1'],
                              'workZipcode'             : [83843, 991631000, 99163],
                              'contractZipcode'         : [83843, 991631000, 99163],
                              'workCountryCode'         : ['USA: STUFF', 'NONE: STUFF', 'USA: STUFF'],
                              'contractCountryCode'     : ['USA: STUFF', 'NONE: STUFF', 'USA: STUFF']})

assert resultDf.equals(clean_zipcodes(testDf))
</code></pre>

<p>Aside from indentations not being proper (didn't convert for SO formatting), the df.ix is not performing as expected. It does not perform any transformations on the contractZipcode or the workZipcode columns. The first row should change to 83843 as noted in the resultDf. </p>

<p>Thank in advance!</p>

<pre><code>In [2]: import pandas as pd


In [3]: testDf = pd.DataFrame({'unique_transaction_id'  : ['1', '1', '1'],
   ...:                            'workZipcode'            : [838431000, 991631000, 99163],
   ...:                            'contractZipcode'        : [838431000, 991631000, 99163],
   ...:                            'workCountryCode'        : ['USA: STUFF', 'NONE: STUFF', 'USA: STUFF'],
   ...:                            'contractCountryCode'    : ['USA: STUFF', 'NONE: STUFF', 'USA: STUFF']}
   ...:                      )
   ...:
   ...: resultDf = pd.DataFrame({'unique_transaction_id'    : ['1', '1', '1'],
   ...:                               'workZipcode'             : [83843, 991631000, 99163],
   ...:                               'contractZipcode'         : [83843, 991631000, 99163],
   ...:                               'workCountryCode'         : ['USA: STUFF', 'NONE: STUFF', 'USA: STUFF'],
   ...:                               'contractCountryCode'     : ['USA: STUFF', 'NONE: STUFF', 'USA: STUFF']})
   ...:
   ...:
   ...:
</code></pre>

<p>Note that an empty slice is returned when you try to index like this:</p>

<pre><code>In [4]: testDf.ix[testDf['workCountryCode'].str.contains('USA') &amp;
                  testDf['workZipcode'].astype(str).str.len() &gt; 5,
                  'workZipcode']
Out[4]: Series([], Name: workZipcode, dtype: int64)
</code></pre>

<p>If you add parentheses around your different filters:</p>

<pre><code>In [5]: testDf.ix[(testDf['workCountryCode'].str.contains('USA'))
                  &amp; (testDf['workZipcode'].astype(str).str.len() &gt; 5),
                  'workZipcode']
Out[5]:
0    838431000
Name: workZipcode, dtype: int64
</code></pre>

<p>you get back what you want. Doesn't matter if you use <code>loc</code> either:</p>

<pre><code>In [6]: testDf.loc[testDf['workCountryCode'].str.contains('USA') &amp;
                   testDf['workZipcode'].astype(str).str.len() &gt; 5, 
                  'workZipcode']
Out[6]: Series([], Name: workZipcode, dtype: int64)
</code></pre>

<p>So here's the cleaned-up function:
I added a few little lambdas for readability's sake.</p>

<pre><code>In [7]: def clean_zipcodes_loc(df):
   ...:     strlen = lambda x: x.astype(str).str.len()
   ...:     floordiv = lambda x: x.astype(int).floordiv(10000)
   ...:
   ...:     df.loc[((strlen(df.workZipcode)) &gt; 5) &amp;
   ...:            df.workCountryCode.str.contains("USA"),
   ...:           'workZipcode'] = floordiv(df.workZipcode)
   ...:
   ...:     df.loc[((strlen(df.contractZipcode)) &gt; 5) &amp;
   ...:            df.contractCountryCode.str.contains("USA"),
   ...:           'contractZipcode'] = floordiv(df.contractZipcode)
   ...:
   ...:     return df
   ...:

In [8]: clean_zipcodes_loc(testDf) == resultDf
Out[8]:
  contractCountryCode contractZipcode unique_transaction_id workCountryCode  \
0                True            True                  True            True
1                True            True                  True            True
2                True            True                  True            True

  workZipcode
0        True
1        True
2        True
</code></pre>

python pandas testing