Skip to content

Instantly share code, notes, and snippets.

@steveharoz
Last active June 18, 2024 04:14
Show Gist options
  • Save steveharoz/42efad650d204da4281eb288c865fc40 to your computer and use it in GitHub Desktop.
Save steveharoz/42efad650d204da4281eb288c865fc40 to your computer and use it in GitHub Desktop.
# put each attribute into a column if possible
# rownames_to_column: (logical) add rownames if the attribute exists
# fix_name_conflicts: (logical) if an attribute name already exists as a column name, find a unique name for it
attributes_to_columns = function(dataframe, rownames_to_column = TRUE, fix_name_conflicts = TRUE) {
for (name in names(attributes(dataframe))) {
value = attr(dataframe, name)
if (name %in% c("names", "class")) {
#skip
}
else if (name == "row.names") {
# TODO: check duplicate column name
if (rownames_to_column)
dataframe = dataframe %>% rownames_to_column()
}
else if (!is.vector(value)) {
warning(
name, ": Skipping attribute because it is of type ", class(value),
"\nOnly vectors can be added as a column.")
}
else if (length(value) == 1 || length(value) == nrow(dataframe)) {
# if not fixing name conflicts and there is one
if (!fix_name_conflicts && name %in% names(dataframe)) {
warning(
name, ": Skipping attribute because a column by that name already exists",
"\nSet `fix_name_conflicts` to TRUE to automatically rename conflicting attributes.")
}
# ensure unqiue name
while(name %in% names(dataframe))
name = paste0("_", name)
# TODO: check if class() can be stored in a data.frame
# add the column
dataframe[name] = value
}
else {
# how to handle vectors with neither 1 nor nrow values?
warning(
name, ": Skipping attribute because it is of length ", length(value),
"\nAttribute must be of length 1 or the tibble length to be added as a column.")
}
}
dataframe
}
# make a simple tibble with attributes
temp = tibble( x=1:10, y=LETTERS[1:10], z=sample(factor(letters[1:3]), 10, TRUE))
attr(temp, "single_value") = "hello"
attr(temp, "many_values") = rnorm(10)
attr(temp, "double") = 1:2
attr(temp, "cars") = rownames_to_column(mtcars)[1:5,]
# view
print(temp)
attributes(temp)
# dataframe with attributes as columns (will warn about incompatible attributes)
temp %>% attributes_to_columns()
# automatically fix duplicate names
temp %>% attributes_to_columns() %>% attributes_to_columns(rownames_to_column = FALSE)
# warn for duplicate names
temp %>% attributes_to_columns() %>% attributes_to_columns(rownames_to_column = FALSE, fix_name_conflicts = FALSE)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment