different ways to access pandas.DataFrame columns
<p>What is the difference between <code>df[columns]</code> and <code>df.loc[:,columns]</code>, both as lvalue and rvalue?</p>

<p>They seem to be interchangeable from the behavioral POV:</p>

<pre><code>&gt;&gt;&gt; df = pd.DataFrame({'x':[1,2,3],'y':['a','b','c']})
&gt;&gt;&gt; df[['x']].equals(df.loc[:,['x']])
True
&gt;&gt;&gt; df.loc[:,'z'] = df.x.apply(str) + df.y
&gt;&gt;&gt; df['a'] = df.x.apply(str) + df.y
&gt;&gt;&gt; df
   x  y   z   a
0  1  a  1a  1a
1  2  b  2b  2b
2  3  c  3c  3c
</code></pre>

<p>I know there is a document somewhere answering this in excruciating details (and I am sure I even saw it once, but a link would be nice), but I am looking at an "executive summary", so to speak.</p>

<p><strong>Specifically</strong>: is one a shortcut for the other, or there is some semantic difference?</p>

<p>PS. This is prompted by the message</p>

<blockquote>
  <p>~/.virtualenvs/wilbur/lib/python2.7/site-packages/pandas/core/indexing.py:465: SettingWithCopyWarning:
  A value is trying to be set on a copy of a slice from a DataFrame.
  Try using .loc[row_indexer,col_indexer] = value instead</p>
</blockquote>

<p>what about timing comparison for a 300K rows DF?</p>

<pre><code>In [22]: big = pd.concat([df] * 10**5, ignore_index=True)

In [23]: %timeit -n 1 -r 1 big['n1'] = big.x.apply(str) + big.y
1 loop, best of 1: 266 ms per loop

In [24]: %timeit -n1 -r 1 big.ix[:, 'n2'] = big.x.apply(str) + big.y
1 loop, best of 1: 317 ms per loop

In [25]: %timeit -n 1 -r 1 big.loc[:, 'n3'] = big.x.apply(str) + big.y
1 loop, best of 1: 333 ms per loop

In [26]: %timeit -n 1 -r 1 big.insert(len(big.columns), 'n4', big.x.apply(str) + big.y)
1 loop, best of 1: 266 ms per loop

In [27]: big.shape
Out[27]: (300000, 6)

In [28]: big.head()
Out[28]:
   x  y  n1  n2  n3  n4
0  1  a  1a  1a  1a  1a
1  2  b  2b  2b  2b  2b
2  3  c  3c  3c  3c  3c
3  1  a  1a  1a  1a  1a
4  2  b  2b  2b  2b  2b
</code></pre>

python pandas dataframe