title: Pandas how to pass DataFrame.assign arguments to add multiple new columns?
body: <p>How can <a href="https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.assign.html" rel="nofollow noreferrer"><code>assign</code></a> be used to return a copy of the original DataFrame <strong>with multiple new columns added?</strong></p>
  <p>Desired result:</p>
  <pre><code>df = pd.DataFrame({'A': range(1, 5), 'B': range(11, 15)})
  &gt;&gt;&gt; df.assign({'C': df.A.apply(lambda x: x ** 2), 'D': df.B * 2})
     A   B   C   D
  0  1  11   1  22
  1  2  12   4  24
  2  3  13   9  26
  3  4  14  16  28
  </code></pre>
  <p>The example above results in:</p>
  <p><code>ValueError: Wrong number of items passed 2, placement implies 1</code>.</p>
  <p>Background:</p>
  <p>The <code>assign</code> function in Pandas takes a copy of the relevant dataframe joined to the newly assigned column, e.g.</p>
  <pre><code>df = df.assign(C=df.B * 2)
  &gt;&gt;&gt; df
     A   B   C
  0  1  11  22
  1  2  12  24
  2  3  13  26
  3  4  14  28
  </code></pre>
  <p>The <a href="http://pandas.pydata.org/pandas-docs/version/0.19.2/generated/pandas.DataFrame.assign.html" rel="nofollow noreferrer">0.19.2 documentation</a> for this function implies that more than one column can be added to the dataframe.</p>
  <blockquote>
  <p><strong>Assigning multiple columns within the same assign is possible, but you cannot reference other columns created within the same assign call.</strong></p>
  </blockquote>
  <p>In addition:</p>
  <blockquote>
  <p>Parameters:<br />
  kwargs : <em>keyword, value pairs</em></p>
  </blockquote>
  <blockquote>
  <p>keywords are the column names.</p>
  </blockquote>
  <p>The source code for the function states that it accepts a dictionary:</p>
  <pre><code>def assign(self, **kwargs):
      &quot;&quot;&quot;
      .. versionadded:: 0.16.0
      Parameters
      ----------
      kwargs : keyword, value pairs
          keywords are the column names. If the values are callable, they are computed 
          on the DataFrame and assigned to the new columns. If the values are not callable, 
          (e.g. a Series, scalar, or array), they are simply assigned.
  
      Notes
      -----
      Since ``kwargs`` is a dictionary, the order of your
      arguments may not be preserved. The make things predicatable,
      the columns are inserted in alphabetical order, at the end of
      your DataFrame. Assigning multiple columns within the same
      ``assign`` is possible, but you cannot reference other columns
      created within the same ``assign`` call.
      &quot;&quot;&quot;
  
      data = self.copy()
  
      # do all calculations first...
      results = {}
      for k, v in kwargs.items():
  
          if callable(v):
              results[k] = v(data)
          else:
              results[k] = v
  
      # ... and then assign
      for k, v in sorted(results.items()):
          data[k] = v
  
      return data
  </code></pre>