title: Apply function converting data frame to character when error returned from API
body: <p>I have written a function to query the CMS National Plan and Provider Enumeration System (NPPES) API.</p>
  <p>I wish to pass in a data frame of NPI values and return their addresses.</p>
  <p>Some of the NPI values are no longer valid and I have tried to build some error handling for these scenarios.</p>
  <p>My error handling <code>if else</code> statement specifies to use a data frame of dimensions 1 row by 6 columns and I have inserted the errored NPI value into row 1 column 1.</p>
  <p>When I use the apply function against my data frame I get a list [1x6] for all the successful API calls but the errored values are just a single character vector.</p>
  <p>I have tried to debug this issue but I can't figure out where the conversion from data frame to character is happening. I would be very grateful if anyone could help me please.</p>
  <p>Here is a dataframe of values I wish to query:</p>
  <pre><code>install.packages(&quot;pacman&quot;)
  library(pacman)
  
  pacman::p_load(tidyverse,data.table,httr,jsonlite)
  
  values &lt;- c(1598727430,
              1083632731,
              1710983663) # LAST VALUE PRODUCES THE ERROR CASE
  
  npi_values &lt;- data.frame(values)
  </code></pre>
  <p>here is the URL for the API:</p>
  <pre><code>path &lt;- &quot;https://npiregistry.cms.hhs.gov/api/?&quot;
  </code></pre>
  <p>My function:</p>
  <pre><code># CREATE A FUNCTION TO PULL NPI INFORMATION FROM THE NPI REGISTRY
  getNPI &lt;- function(object) {
    request &lt;- httr::GET(
      url = path,
      query = list(
        version = &quot;2.0&quot;,
        number = object
      )
    )
    Sys.sleep(0.25)
    
    warn_for_status(request)
  
    npi_details &lt;- content(request,
      as = &quot;text&quot;,
      encoding = &quot;UTF-8&quot;
    ) %&gt;%
      fromJSON(.,
        flatten = TRUE
      ) %&gt;%
      data.frame()
    # IF THE API THROWS BACK A RESULT WHERE THE COLUMN NAMES CONTAIN 'ERROR'
    # THEN ASSIGN ALL THE ROW VALUES TO NA AND ADD THE NPI VALUE TO THE FIRST
    # COLUMN
    if (any(grepl(&quot;ERROR&quot;, toupper(colnames(npi_details))))) {
      
      npi_details &lt;- as.data.frame(matrix(NA,ncol = 6,nrow = 1)) %&gt;% 
        dplyr::rename(`NPI NUMBER` = V1,
               `CMS REF ADDRESS 1` = V2,
               `CMS REF ADDRESS 2` = V3,
               `CMS REF CITY` = V4,
               `CMS REF STATE` = V5,
               `CMS REF ZIP` = V6)
      
      npi_details[1,1] &lt;- object
      
      # ELSE IF THE DATA FRAME DOES NOT CONTAIN 'ERROR' THEN RUN THIS CHUNK
    } else {
      select(npi_details, contains(c(&quot;addresses&quot;, &quot;number&quot;))) %&gt;%
        unnest(c(contains(&quot;address&quot;))) %&gt;%
        filter(address_purpose == &quot;MAILING&quot;) %&gt;%
        rename_all(.funs = toupper) %&gt;%
        select(
          `NPI NUMBER` = RESULTS.NUMBER,
          -COUNTRY_CODE,
          -COUNTRY_NAME,
          -ADDRESS_PURPOSE,
          -ADDRESS_TYPE,
          `CMS REF ADDRESS 1` = ADDRESS_1,
          `CMS REF ADDRESS 2` = ADDRESS_2,
          `CMS REF CITY` = CITY,
          `CMS REF STATE` = STATE,
          `CMS REF ZIP` = POSTAL_CODE
        )
    }
  }
  </code></pre>
  <p>I then apply this function against the data frame of NPI values above:</p>
  <pre><code>out &lt;- apply(npi_values, 1, getNPI)
  </code></pre>
  <p>When I apply this to my real dataset you can see below that the error case is converted to a character even though I specify a data frame of size 1 row by 6 columns</p>
  <p><strong>Based on feedback from @akrun I have modified my apply statement to include wrapping the getNPI function in a list, see below:</strong></p>
  <pre><code>out &lt;- apply(npi_values, 1, function(x) list(getNPI(x)))
  </code></pre>
  <p>The structure of <code>out</code> now looks as follows:</p>
  <pre><code>str(out)
  List of 3
   $ :List of 1
    ..$ : tibble [1 × 6] (S3: tbl_df/tbl/data.frame)
    .. ..$ NPI NUMBER       : int 1598727430
    .. ..$ CMS REF ADDRESS 1: chr &quot;PO BOX 17567&quot;
    .. ..$ CMS REF ADDRESS 2: chr &quot;&quot;
    .. ..$ CMS REF CITY     : chr &quot;PENSACOLA&quot;
    .. ..$ CMS REF STATE    : chr &quot;FL&quot;
    .. ..$ CMS REF ZIP      : chr &quot;325227567&quot;
   $ :List of 1
    ..$ : tibble [1 × 6] (S3: tbl_df/tbl/data.frame)
    .. ..$ NPI NUMBER       : int 1083632731
    .. ..$ CMS REF ADDRESS 1: chr &quot;PO BOX 17326&quot;
    .. ..$ CMS REF ADDRESS 2: chr &quot;&quot;
    .. ..$ CMS REF CITY     : chr &quot;DENVER&quot;
    .. ..$ CMS REF STATE    : chr &quot;CO&quot;
    .. ..$ CMS REF ZIP      : chr &quot;802170326&quot;
   $ :List of 1
    ..$ : Named num 1.71e+09
    .. ..- attr(*, &quot;names&quot;)= chr &quot;values&quot;
  </code></pre>
  <p>When I try to collapse these lists into data frame of 3 rows by 6 columns, the last case (errored case) drops into a 7th column which is not desired. I wish to have the value from the 3 case stored in the first column with remaining values filled with NA.</p>
  <p>Desired outcome:</p>
  <pre><code>`NPI NUMBER` &lt;- c(1598727430,1083632731,1710983663)
  `CMS REF ADDRESS 1` &lt;- c(&quot;PO BOX 17567&quot;,&quot;PO BOX 17326&quot;,NA)
  `CMS REF ADDRESS 2` &lt;- c(&quot;&quot;,&quot;&quot;,NA)
  `CMS REF CITY` &lt;- c(&quot;PENSACOLA&quot;,&quot;DENVER&quot;,NA)
  `CMS REF STATE` &lt;- c(&quot;FL&quot;,&quot;CO&quot;,NA)
  `CMS REF ZIP` &lt;- c(&quot;325227567&quot;,&quot;802170326&quot;,NA)
  desired &lt;- data.frame(`NPI NUMBER`,`CMS REF ADDRESS 1`,`CMS REF ADDRESS 2`,`CMS REF CITY`,`CMS REF STATE`,`CMS REF ZIP`)
  </code></pre>
  <p><a href="https://i.stack.imgur.com/F0rLX.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/F0rLX.png" alt="enter image description here" /></a></p>
  <p><a href="https://i.stack.imgur.com/1ILeS.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/1ILeS.png" alt="enter image description here" /></a></p>