Изменить буквенный регистр имен столбцов

У меня есть большое количество наборов данных, каждый из которых содержит длинный список имен столбцов. В некоторых файлах имена столбцов имеют прописные буквы, а в некоторых файлах только первая буква имен столбцов капитализируется. Мне нужно добавить наборы данных и подумал, что самый простой способ сопоставить имена столбцов между наборами данных - это преобразовать имена всех капиталов в имена только с заглавной буквой в первую букву.

Я надеюсь найти общее решение, возможно даже однострочное.

Вот мой примерный набор данных. Именные имена включены в операторы names.

my.data2 <-  "
landuse units grade CLAY    LINCOLN  BASINANDRANGE  MCCARTNEY  MAPLE
apple   acres AAA     0         2          3             4         6
apple   acres AA   1000       900         NA            NA       700
pear    acres AA   10.0        20         NA          30.0        40
peach   acres AAA   500       400        350           300       200
"
my.data2 <- read.table(textConnection(my.data2), header=TRUE)

names(my.data2)[names(my.data2)=="CLAY"]            <- "Clay"
names(my.data2)[names(my.data2)=="BASINANDRANGE"]   <- "BasinandRange"
names(my.data2)[names(my.data2)=="LINCOLN"]         <- "Lincoln"
names(my.data2)[names(my.data2)=="MCCARTNEY"]       <- "McCartney"
names(my.data2)[names(my.data2)=="MAPLE"]           <- "Maple"

my.data2

Обратите внимание, что я включил имена McCartney и BasinandRange, чтобы сделать вещи более реалистичными и сложными. Однако, если я могу найти однострочный экземпляр, чтобы иметь дело с 95% имен и использовать приведенные выше выражения names для решения таких сложностей, как McCartney и BasinandRange, это было бы здорово.

Я искал в Интернете, в том числе архивы StackOverflow, не найдя решения. Извините, если я пропустил это. Спасибо за любую помощь.

Ответ 1

Вот один лайнер, реализующий "самый простой способ сопоставить имена столбцов между наборами данных", о которых я могу думать:

## Columns 1:3 left unaltered since they are not place names.
names(my.data2)[-1:-3] <- tolower(names(my.data2)[-1:-3])

## View the results
names(my.data2)
# [1] "landuse"       "units"         "grade"         "clay"         
# [5] "lincoln"       "basinandrange" "mccartney"     "maple"   

Ответ 2

data.table синтаксис, я считаю, сэкономит больше времени и эффективности. его также однострочное утверждение, даже короче.

setnames(my.data2, tolower(names(my.data2[4:8])))

#   landuse units grade clay lincoln basinandrange mccartney maple
#1:   apple acres   AAA    0       2             3         4     6
#2:   apple acres    AA 1000     900            NA        NA   700
#3:    pear acres    AA   10      20            NA        30    40
#4:   peach acres   AAA  500     400           350       300   200

Ответ 3

Я использовал ответ Джоша О'Брайена, но в конце концов написал код ниже, который создает имена столбцов с первой буквой в верхнем регистре и другие буквы в нижнем регистре, за несколькими исключениями обрабатываются как в исходном сообщении. Ниже я использовал тот же набор данных, что и в исходном сообщении, но прочитал эти данные в R по-разному, где n.col определяет количество столбцов в файле данных:

n.col <- as.numeric(length(scan("c:/users/mark w miller/simple R programs/names_with_capital_letters.txt", 
         what="character", nlines=1)))

my.data2 <- read.table(file = "c:/users/mark w miller/simple R programs/names_with_capital_letters.txt", 
            na.string=NA, header = T, colClasses = c('character', 'character', 'character', 
            rep('numeric', (n.col[1] - 3))))

first.letter  <- substring(names(my.data2)[-1:-3], 1, 1)
other.letters <- tolower(substring(names(my.data2)[-1:-3], 2))
newnames      <- paste(first.letter, other.letters, sep="")

names(my.data2)[-1:-3] <- newnames
names(my.data2)[names(my.data2)=="Basinandrange"]   <- "BasinandRange"
names(my.data2)[names(my.data2)=="Mccartney"]       <- "McCartney"

my.data2

#   landuse units grade Clay Lincoln BasinandRange McCartney Maple
# 1   apple acres   AAA    0       2             3         4     6
# 2   apple acres    AA 1000     900            NA        NA   700
# 3    pear acres    AA   10      20            NA        30    40
# 4   peach acres   AAA  500     400           350       300   200

Ответ 4

современное решение

Это уже работа для janitor::clean_names(), просто выберите case параметр, который подходит вам.

Ответ 5

"Чистое" решение:

library(dplyr)

my.data2.mod <- my.data2 %>% 
  rename_at(c("CLAY", "LINCOLN", "BASINANDRANGE", "MCCARTNEY",  "MAPLE"),
            .funs = tolower)

names(my.data2.mod) 
# [1] "landuse"       "units"         "grade"         "clay"         
# [5] "lincoln"       "basinandrange" "mccartney"     "maple"   

Кроме того, чтобы ответить на исходный вопрос и оставить заглавные буквы в некоторых случаях, вы можете использовать пакет snakecase:

library(snakecase)

my.data2.mod = my.data2 %>% 
  rename_at(
    c("CLAY", "LINCOLN", "BASINANDRANGE", "MCCARTNEY",  "MAPLE"),
    .funs = list(
      ~ to_upper_camel_case(., 
                            abbreviations = c("McCartney", "BasinandRange")
                            )
      )
    )

names(my.data2.mod)
# [1] "landuse"       "units"         "grade"         "Clay"         
# [5] "Lincoln"       "BasinandRange" "McCartney"     "Maple"