Dataframe only appears in console, not in environment (Rstudio)

Viewed 931

I am quite unexperienced in R/Rstudio, but I am currently working on creating a package for my job where I have run into a problem I can't figure out. I have created several functions already where I use return() to get the dataframe created by the code to appear in my environment. However, in this one I only get the first 38 rows of the dataframe shown in the R console.

The code for the function:

widen <- function(projectpath) {

  project.df <- readr::read_csv(file = projectpath)

  projectwide.df <- project.df %>%
    dplyr::select(-c(1, Detection_limit)) %>%
    tidyr::pivot_wider(names_from = Element, values_from = Concentration)

  projectwide.df <- as.data.frame(projectwide.df)

  return(projectwide.df)

}

I tried this with and without the as.data.frame() and also tried only data.frame, but neither worked. It did work, however, when I ran the code by itself (not as a function) when testing it. Of course, then I did not have to use the return() function, which is where the problem seems to be.

At first my problem was that the data appeared as a tibble rather than a dataframe, but I believe this is no longer my problem as this appears above the dataframe in the console, and if I have understood my previous output correctly, this means that it is in fact a dataframe:

cols(
  X1 = col_double(),
  Sample = col_character(),
  Date.x = col_character(),
  Filter_type = col_character(),
  Filter_size = col_double(),
  Filter_box_nr = col_double(),
  Filter_blank = col_character(),
  Volume = col_double(),
  Date.y = col_date(format = ""),
  Day = col_double(),
  Treatment = col_character(),
  Element = col_character(),
  Concentration = col_double(),
  Detection_limit = col_double()
)

Here is one of my other functions where I use return(), it works here:

importxrf <- function(datapath, infopath) {

  datafile.df <- importdata(datapath = datapath)

  infofile.df <- importinfo(infopath = infopath)

  projectfile.df <- dplyr::inner_join(datafile.df, infofile.df, by = "Sample")

  notinprojectfile.df <- dplyr::anti_join(datafile.df, infofile.df, by = "Sample")

  if(nrow(notinprojectfile.df) > 0) {
    warning("WARNING! There are samples that do not match between your raw data file and information file.")
  }

  return(projectfile.df)

}

As far as I can see, the only difference between these two functions is the use of as.data.frame(), but as I mentioned, it does not work without this either. If anyone can help me figure this out, I would be very grateful! Thanks

EDIT: Here is a version of the code where I create the dataframe inside the code so it is reproducible. This just shows the first 5 rows of an actual dataset I have.

widennn <- function() {

  Sample <- c("COM001", "COM001", "COM001", "COM001", "COM001")
  Element <- c("C", "N", "O", "Na", "Mg")
  Concentration <- c(-4.19727307987776, 0.292013243234358, 0.328051062623146, -0.0555794187038898, 0.0353942596959773)
  Detection_limit <- c(1.22193802149026, 0.312338639119395, 0.0322146560280234, 0.0362539069926691, 0.00465264605182871)

  firstrows.df <- data.frame(Sample, Element, Concentration, Detection_limit)

  projectwide.df <- firstrows.df %>%
    dplyr::select(-c(Detection_limit)) %>%
    tidyr::pivot_wider(names_from = Element, values_from = Concentration)

  projectwide.df <- as.data.frame(projectwide.df)

  return(projectwide.df)

}
1 Answers

I think the issue here is related to scoping. When you create a function that assigns an object, that object only exists in special environment created by that function. So it cannot be accessed from the outside. The variables created by the functions are lost when the function is completed. You can assign objects to whatever environment you want. You can assign an object to the global environment with <<- function. However, its considered best practice to let the user manually assign objects. This is easier to troubleshoot and gives the user more control. Please look at the two ways of assigning below:

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

# Not optimal
widennn <- function() {
  
  Sample <- c("COM001", "COM001", "COM001", "COM001", "COM001")
  Element <- c("C", "N", "O", "Na", "Mg")
  Concentration <- c(-4.19727307987776, 0.292013243234358, 0.328051062623146, -0.0555794187038898, 0.0353942596959773)
  Detection_limit <- c(1.22193802149026, 0.312338639119395, 0.0322146560280234, 0.0362539069926691, 0.00465264605182871)
  
  firstrows.df <- data.frame(Sample, Element, Concentration, Detection_limit)
  
  projectwide.df <- firstrows.df %>%
    dplyr::select(-c(Detection_limit)) %>%
    tidyr::pivot_wider(names_from = Element, values_from = Concentration)
  # This is not recommended
  projectwide.df <<- as.data.frame(projectwide.df)
  #return(projectwide.df)
}

widennn()

projectwide.df
#>   Sample         C         N         O          Na         Mg
#> 1 COM001 -4.197273 0.2920132 0.3280511 -0.05557942 0.03539426


# Better 
widennn <- function() {
  
  Sample <- c("COM001", "COM001", "COM001", "COM001", "COM001")
  Element <- c("C", "N", "O", "Na", "Mg")
  Concentration <- c(-4.19727307987776, 0.292013243234358, 0.328051062623146, -0.0555794187038898, 0.0353942596959773)
  Detection_limit <- c(1.22193802149026, 0.312338639119395, 0.0322146560280234, 0.0362539069926691, 0.00465264605182871)
  
  firstrows.df <- data.frame(Sample, Element, Concentration, Detection_limit)
  
  projectwide.df <- firstrows.df %>%
    dplyr::select(-c(Detection_limit)) %>%
    tidyr::pivot_wider(names_from = Element, values_from = Concentration)
  
  return(projectwide.df)
}

output <- widennn()

output
#> # A tibble: 1 x 6
#>   Sample     C     N     O      Na     Mg
#>   <chr>  <dbl> <dbl> <dbl>   <dbl>  <dbl>
#> 1 COM001 -4.20 0.292 0.328 -0.0556 0.0354

Created on 2020-12-07 by the reprex package (v0.3.0)

Please correct me if I have misunderstood the question.

Related