R - изменить имена столбцов переменных в функции

Ниже приведен function под названием change_names, который работает, но только с определенным именем фрейма данных. Короче говоря, у меня проблемы с пониманием того, как управлять функцией assign, чтобы она могла обрабатывать разные имена фреймов данных.

function в основном меняет имена столбцов файлов, когда я их читаю в for loop. Например, один файл может иметь имя столбца 'A', которое должно быть 'X', а другой файл может иметь имя столбца 'D', которое также должно называться 'X'.

Я пробовал несколько разных выходов, чтобы фактически изменить исходный фрейм данных, 'tempPullList', но мне нужно иметь возможность использовать эту функцию в другом фрейме данных.

#====example different files====
file1 <- data.frame(A = rep(1:10), Y = rep(c("Yellow","Red","Purpule","Green","Blue"), 2),
                    Z = rep(c("Drink", "Food"), 5))

file2 <- data.frame(D = rep(1:10), B = rep(c("Brown","Pink","Purpule","Green","Blue"), 2),
                    Z = rep(c("Drink", "Food"), 5))

file3 <- data.frame(X = rep(1:10), B = rep(c("Brown","Pink","Purpule","Green","Blue"), 2),
                    C = rep(c("Drink", "Food"), 5))

file_list <- list(file1, file2, file3)


#====Package Bank====
library(data.table)
library(dplyr)

#====Function====
change_names <- function(x){

  #a list of columns to be renamed
  #through out the files
  chgCols <- c("A",
               "B",
               "C",
               "D")

  #the names the columns will be changed to
  namekey <- c(A = "X",
               B = "Y",
               C = "Z",
               D = "X")

  chgCols <- match(chgCols, colnames(x))               #find any unwanted column indexes in data frame
  chgCols <- colnames(x[, chgCols[!is.na(chgCols)]])   #match indexes to column names w/o NA's

  x <- x %>%                                           #rename associated columns
    plyr::rename(namekey[chgCols])                     #from 'namekey' in dataframe

  assign('tempPullList', x, envir = .GlobalEnv)

}



#====Read in Files====

PullList <- data.frame()
for(file in 1:length(file_list)){
  tempPullList <- data.frame(file_list[file])
  print(file)

  change_names(x = tempPullList)
  PullList <- rbindlist(list(PullList, tempPullList),
                          fill = T)
}

Опять же, прямо сейчас я могу сделать это, только когда фрейм данных называется «tempPullList». Мне нужно иметь возможность сделать это с другим фреймом данных.

Я новичок в написании функций и особенно в назначении переменных внутри функций. Я бы хотел, чтобы эта функция была максимально вариативной. В настоящее время я работаю над тем, чтобы сделать chgCols и namekey входными. Так что любые советы по этому поводу тоже будут полезны.

Можете ли вы объяснить взаимосвязь между tempPullList и x? Или приведите пример типичного ввода и ожидаемого результата?

Zach 09.08.2018 23:39

В дальнейшем у меня возникли проблемы с пониманием, почему вы просто не использовали бы return(x) вместо того, чтобы возиться с пространствами имен, что, как правило, не является хорошей идеей.

Zach 09.08.2018 23:42

К вашему сведению, у вас не может быть фрейма данных с двумя столбцами с именем «X». Чтобы предотвратить проблему с именованием, r, вероятно, автоматически переименует второй столбец «X» в «X.1».

Adam Sampson 09.08.2018 23:51

Я был неправ ... вы можете указать одно и то же имя столбца дважды ... но это вызовет проблемы позже. df $ X проигнорирует второй столбец.

Adam Sampson 10.08.2018 00:02

@AdamSampson У меня есть несколько файлов, которые я читаю. В одном из них может быть столбец «A», а в другом - столбец «D», но они ДОЛЖНЫ быть помечены как «X», поскольку это одно и то же. На самом деле заголовки столбцов каждого файла расположены повсюду. Подумайте, «ID», «ItemID», «Item.Id», «ItemId» и т. д. Я хочу, чтобы все они были «ItemId». Я заменил ItemId на X для простоты.

alexb523 10.08.2018 00:08

@Zach Я создал пример с вводом и желаемым выводом. но мне нужно иметь возможность делать это с разными фреймами данных, а не с tempPullList. Кроме того, не могли бы вы объяснить, что вы имеете в виду, говоря об использовании функции return, если она все еще актуальна?

alexb523 10.08.2018 00:17

Попался. Если разные файлы имеют разные имена столбцов, это имеет больше смысла.

Adam Sampson 10.08.2018 00:25

Кстати: с функцией assign значение для глобальной среды - "Плохая вещь (тм)". Это мог работает для вас какое-то время. Это почти всегда будет вызывать проблемы, если другим придется его использовать, если только вы не приложите больших усилий для документирования и работы с вещами. Пакет quantmod делает это, и многие вопросы по SO являются прямым результатом (или непосредственно усложняются) таким поведением. Пожалуйста, нажмите кнопку I Believe на этом.

r2evans 10.08.2018 01:31

@ r2evans, что было бы лучше?

alexb523 10.08.2018 15:37

Я новичок в написании функций и особенно в назначении переменных внутри функций. Я бы хотел, чтобы эта функция была максимально вариативной. В настоящее время я работаю над тем, чтобы сделать chgCols и namekey входными. Так что любые советы по этому поводу тоже будут полезны.

alexb523 10.08.2018 16:25

В целом, я думаю, что общее мнение (среди тех, кто «адепт» в программировании) состоит в том, что "функциональное программирование" более интуитивно понятен, намного проще устранять неполадки / поддерживать и, избегая "побочный эффект", многих других вещей «Just Work (tm)». Есть пакеты, которые предлагают побочный эффект (например, quantmod), есть хорошие функции, которые должен работают с побочным эффектом (write.csv). Предпосылка такова: явным образом предоставьте функции все, что ей нужно.

r2evans 10.08.2018 19:18

@ r2evans, как в этом конкретном случае явно указать функции для обработки любого фрейма данных, а не только фрейма данных с именем 'tempPullList'? Я делаю это несколько раз в разрабатываемом коде. Несколько раз для фрейма данных под названием «tempPullList», а затем это необходимо для двух других фреймов данных.

alexb523 15.08.2018 23:33

Если у вас есть функция, укажите ее в своем вопросе, а не только код изнутри.

r2evans 16.08.2018 00:06
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
13
1 020
1

Ответы 1

Пример данных:

column_name_lookup <- data.frame(orig = c("a","b","c","d"),
                                 new = c("X","Y","z","X"),
                                 stringsAsFactors = FALSE)

test_df <- data.frame(a = 1:5,
                      c = 2:6,
                      b = 3:7,
                      e = 4:8,
                      d = 5:9)
  a c b e d
1 1 2 3 4 5
2 2 3 4 5 6
3 3 4 5 6 7
4 4 5 6 7 8
5 5 6 7 8 9

Код для изменения имен:

new_names <- column_name_lookup$new[match(names(test_df),column_name_lookup$orig)]

names(test_df) <- ifelse(is.na(new_names),names(test_df),new_names)
  X z Y e X
1 1 2 3 4 5
2 2 3 4 5 6
3 3 4 5 6 7
4 4 5 6 7 8
5 5 6 7 8 9

Пожалуйста, посмотрите мою правку с более воспроизводимым примером.

alexb523 10.08.2018 00:20

Другие вопросы по теме