R Container for Multiple data.frame with a Brief Description of the Content of the data.frame
One approach
If the description is to serve only as a metadata, R allows you to add any number of metadata to objects with attributes feature. you can add it as an attribute for the data.frame object.
attr(sub_data, &quot;Description&quot;) &lt;- &quot;Contains all sumscales + sociodemographics, names abbreviated&quot;

# Description now shows in the data frame structure 
str(sub_data)
# 'data.frame': 5 obs. of  2 variables:
#  $ x: num  2 3 5 1 6
# $ y: num  20 30 10 302 5
# - attr(*, &quot;Description&quot;)= chr &quot;Contains all sumscales + sociodemographics, names # abbreviated&quot;

#You can access the Description only
attributes(sub_data)$Description
# [1] &quot;Contains all sumscales + sociodemographics, names abbreviated&quot;

However, custom attributes come with limitations.They are not persistent when you perform certain operations on objects such as subsetting. Here is an example using same object with the new Description attribute we just added. If we subset the data, the custom attribute will be lost.
sub2_data &lt;- sub_data[,&quot;x&quot;, drop = FALSE]

attributes(sub2_data)$Description
# NULL


Alternative approach
You can use the same idea of creating a container within container. However, instead of creating a list that contains data frames, you can create a data.frame within a data.frame. This makes it easier to access and manipulate. You can access the inner data frame by adding second $
# Assigning new column `data` to hold data frames 
index_df$data &lt;- index_list

# We can access Description 
index_df$Description
# [1] &quot;Contains all sumscales + sociodemographics, names abbreviated&quot;
# [2] &quot;Only sum scores for the UV Scale&quot;  

# Accessing Data 
index_df$data$sub_data
#  x   y
#1 2  20
#2 3  30
#3 5  10
#4 1 302
#5 6   5

str(index_df)
# 'data.frame': 2 obs. of  3 variables:
#  $ Data.Frame : chr  &quot;sub_data&quot; &quot;uv_newScale&quot;
# $ Description: chr  &quot;Contains all sumscales + sociodemographics, names abbreviated&quot; &quot;Only sum scores for the UV Scale&quot;
# $ data       :List of 2
#  ..$ sub_data   :'data.frame':    5 obs. of  2 variables:
#  .. ..$ x: num  2 3 5 1 6
#  .. ..$ y: num  20 30 10 302 5
#  ..$ uv_newScale:'data.frame':    5 obs. of  2 variables:
#  .. ..$ item1: num  2 3 5 1 6
#  .. ..$ item2: num  3 5 1 3 2

Efficiency
The first approach is more efficient than the second in terms of memory footprint. Here is a comparison between objects sizes in bytes.
# Creating one data frame within one data frame for comparison
list_df &lt;- list(sub_data=sub_data)
dfs &lt;- data.frame(&quot;Data.Frame&quot;=&quot;sub_data&quot;,
             &quot;Description&quot;=&quot;Contains all sumscales + sociodemographics, names abbreviated&quot;)

dfs$data &lt;- list_df 

# Adding attributes
attr(sub_data, &quot;Description&quot;) &lt;- &quot;Contains all sumscales + sociodemographics, names abbreviated&quot;
 

# Memory Size in bytes
object.size(dfs)
# 2376 bytes
object.size(sub_data)
# 1224 bytes