Matt
Matt

Reputation: 7385

Rename columns existing in data.frame while maintaining case

I have two data.frames:

df <- data.frame(Cats = c(1,2,3), Dogs = c(1,2,3), Bears = c(1,2,3))

df_lower <- structure(list(cats = c(1, 2, 3), n = c(1, 1, 1), percent = c(0.333333333333333, 
0.333333333333333, 0.333333333333333)), class = "data.frame", row.names = c(NA, 
-3L), core = structure(list(cats = c(1, 2, 3), n = c(1, 1, 1), 
    percent = c(0.333333333333333, 0.333333333333333, 0.333333333333333
    )), class = "data.frame", row.names = c(NA, -3L)), tabyl_type = "one_way")

df:

  Cats Dogs Bears
1    1    1     1
2    2    2     2
3    3    3     3

df_lower:

  cats n   percent
1    1 1 0.3333333
2    2 1 0.3333333
3    3 1 0.3333333

How can I rename the columns in df_lower by detecting the names that are present in df, and then matching them?

Expected output:

  Cats n   percent
1    1 1 0.3333333
2    2 1 0.3333333
3    3 1 0.3333333

Upvotes: 2

Views: 93

Answers (2)

jordan
jordan

Reputation: 178

df <- data.frame(
  Cats = 1:3,
  Dogs = 1:3,
  Bears = 1:3
)

df_lower <- data.frame(
  cats = 1:3,
  n = rep(1, 3),
  percent = rep(1/3, 3)
)

# Is this what you wanted?
df_lower <- janitor::as_tabyl(df_lower)

# Get column names
cn1 <- colnames(df)
cn2 <- colnames(df_lower)

# Returns the index of cn2 for each cn1 match
# cn2 is already all lowercase
ind <- match(cn2, tolower(cn1), nomatch = 0L)
# assign new colum names
colnames(df_lower)[ind > 0] <- cn1[ind]

df
#>   Cats Dogs Bears
#> 1    1    1     1
#> 2    2    2     2
#> 3    3    3     3
df_lower
#>  Cats n   percent
#>     1 1 0.3333333
#>     2 1 0.3333333
#>     3 1 0.3333333

Created on 2021-02-18 by the reprex package (v1.0.0)

Upvotes: 0

akrun
akrun

Reputation: 887008

We convert the column names of the first to lower case, then do a match

i1 <- match(names(df_lower), tolower(names(df)), nomatch = 0)
i2 <- i1 > 0
nm1 <- names(df_lower)[i2]
df_lower <- df_lower %>%
    rename_at(vars(nm1), ~  names(df)[i1[i2]])

-output

df_lower
#   Cats n   percent
#1    1 1 0.3333333
#2    2 1 0.3333333
#3    3 1 0.3333333

Or using base R

names(df_lower)[i2] <- names(df)[i1[i2]]

Upvotes: 1

Related Questions