Ниже приведен 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 входными. Так что любые советы по этому поводу тоже будут полезны.
В дальнейшем у меня возникли проблемы с пониманием, почему вы просто не использовали бы return(x) вместо того, чтобы возиться с пространствами имен, что, как правило, не является хорошей идеей.
К вашему сведению, у вас не может быть фрейма данных с двумя столбцами с именем «X». Чтобы предотвратить проблему с именованием, r, вероятно, автоматически переименует второй столбец «X» в «X.1».
Я был неправ ... вы можете указать одно и то же имя столбца дважды ... но это вызовет проблемы позже. df $ X проигнорирует второй столбец.
@AdamSampson У меня есть несколько файлов, которые я читаю. В одном из них может быть столбец «A», а в другом - столбец «D», но они ДОЛЖНЫ быть помечены как «X», поскольку это одно и то же. На самом деле заголовки столбцов каждого файла расположены повсюду. Подумайте, «ID», «ItemID», «Item.Id», «ItemId» и т. д. Я хочу, чтобы все они были «ItemId». Я заменил ItemId на X для простоты.
@Zach Я создал пример с вводом и желаемым выводом. но мне нужно иметь возможность делать это с разными фреймами данных, а не с tempPullList. Кроме того, не могли бы вы объяснить, что вы имеете в виду, говоря об использовании функции return, если она все еще актуальна?
Попался. Если разные файлы имеют разные имена столбцов, это имеет больше смысла.
Кстати: с функцией assign значение для глобальной среды - "Плохая вещь (тм)". Это мог работает для вас какое-то время. Это почти всегда будет вызывать проблемы, если другим придется его использовать, если только вы не приложите больших усилий для документирования и работы с вещами. Пакет quantmod делает это, и многие вопросы по SO являются прямым результатом (или непосредственно усложняются) таким поведением. Пожалуйста, нажмите кнопку I Believe на этом.
@ r2evans, что было бы лучше?
Я новичок в написании функций и особенно в назначении переменных внутри функций. Я бы хотел, чтобы эта функция была максимально вариативной. В настоящее время я работаю над тем, чтобы сделать chgCols и namekey входными. Так что любые советы по этому поводу тоже будут полезны.
В целом, я думаю, что общее мнение (среди тех, кто «адепт» в программировании) состоит в том, что "функциональное программирование" более интуитивно понятен, намного проще устранять неполадки / поддерживать и, избегая "побочный эффект", многих других вещей «Just Work (tm)». Есть пакеты, которые предлагают побочный эффект (например, quantmod), есть хорошие функции, которые должен работают с побочным эффектом (write.csv). Предпосылка такова: явным образом предоставьте функции все, что ей нужно.
@ r2evans, как в этом конкретном случае явно указать функции для обработки любого фрейма данных, а не только фрейма данных с именем 'tempPullList'? Я делаю это несколько раз в разрабатываемом коде. Несколько раз для фрейма данных под названием «tempPullList», а затем это необходимо для двух других фреймов данных.
Если у вас есть функция, укажите ее в своем вопросе, а не только код изнутри.





Пример данных:
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
Пожалуйста, посмотрите мою правку с более воспроизводимым примером.
Можете ли вы объяснить взаимосвязь между
tempPullListиx? Или приведите пример типичного ввода и ожидаемого результата?