2015-11-06 12 views
5

Я пытаюсь использовать lapply в списке фреймов данных; но не удается правильно передать параметры (я думаю).Использование lapply для изменения имен столбцов списка фреймов данных

Список кадров данных:

df1 <- data.frame(A = 1:10, B= 11:20) 
df2 <- data.frame(A = 21:30, B = 31:40) 

listDF <- list(df1, df2,df3) #multiple data frames w. way less columns than the length of vector todos 

вектор с именами столбцов:

todos <-c('col1','col2', ......'colN') 

Я хотел бы изменить имена столбцов с помощью lapply:

lapply (listDF, function(x) { colnames(x)[2:length(x)] <-todos[1:length(x)-1] } ) 

но это Безразлично вообще не изменяйте имена. Я не передаю сами кадры данных, а что-то еще? Я просто хочу изменить имена, а не возвращать результат на новый объект.

Заранее спасибо, стр.

+0

не будет работать из-за вызова * R в по значению * – jogo

+1

Просто добавьте 'x' до конца' lapply (listDF, функция (х) {COLNAMES (х) [2: длина (х)] < -todos [1: length (x) -1]; x}) '. Ваша функция в письменном виде не имеет возвращаемого значения. –

+1

Не связано с вопросом, но я думаю, что '1: length (x) -1' является общей ошибкой (иногда не вредной). Правильная строка: '1: (length (x) -1)' (beware priority!) – nicola

ответ

11

Вы также можете использовать setNames, если вы хотите заменить все столбцы

df1 <- data.frame(A = 1:10, B= 11:20) 
df2 <- data.frame(A = 21:30, B = 31:40) 

listDF <- list(df1, df2) 
new_col_name <- c("C", "D") 

lapply(listDF, setNames, nm = new_col_name) 
## [[1]] 
##  C D 
## 1 1 11 
## 2 2 12 
## 3 3 13 
## 4 4 14 
## 5 5 15 
## 6 6 16 
## 7 7 17 
## 8 8 18 
## 9 9 19 
## 10 10 20 

## [[2]] 
##  C D 
## 1 21 31 
## 2 22 32 
## 3 23 33 
## 4 24 34 
## 5 25 35 
## 6 26 36 
## 7 27 37 
## 8 28 38 
## 9 29 39 
## 10 30 40 

Если вам необходимо заменить только часть имен столбцов, то вы можете использовать раствор @Jogo

lapply(listDF, function(df) { 
    names(df)[-1] <- new_col_name[-ncol(df)] 
    df 
}) 

и последнее точка, в R существует разница между A: B - 1 и а: (б - 1)

1:10 - 1 
## [1] 0 1 2 3 4 5 6 7 8 9 

1:(10 - 1) 
## [1] 1 2 3 4 5 6 7 8 9 

EDIT

Если вы хотите изменить имена столбцов в data.frame в глобальной среде из списка, вы можете использовать list2env, но я не уверен, что это лучший способ для достижения вы хотите хотеть. Вам также необходимо изменить свой список и использовать именованный список, имя должно совпадать с именем data.frame, которое вам нужно заменить.

listDF <- list(df1 = df1, df2 = df2) 

new_col_name <- c("C", "D") 

listDF <- lapply(listDF, function(df) { 
    names(df)[-1] <- new_col_name[-ncol(df)] 
    df 
}) 

list2env(listDF, envir = .GlobalEnv) 
str(df1) 
## 'data.frame': 10 obs. of 2 variables: 
## $ A: int 1 2 3 4 5 6 7 8 9 10 
## $ C: int 11 12 13 14 15 16 17 18 19 20 
+0

Проверьте выходные данные и код OP. Строка 'colnames (x) [2: length (x)]' указывает, что замена начинается со второго столбца. –

+0

@PierreLafortune Спасибо Пьер вы правы, я сделал некоторую корректировку – dickoa

+0

Извините dickoa, но lapply только изменяет имена столбцов * внутри * списка (так что df1 и df2 все еще имеют оригинальные имена. !!). Я также попытался добавить «х» от Пьера, но все же это не делает трюк. Я использую этот список только для хранения длинного списка DF, но не для того, чтобы мне хотелось внести изменения внутри самого списка. Есть идеи? спасибо – user3310782

1

попробовать это:

lapply (listDF, function(x) { 
    names(x)[-1] <- todos[-length(x)] 
    x 
}) 

вы получите новый список с измененным dataframes. Если вы хотите, чтобы манипулировать listDF непосредственно:

for (i in 1:length(listDF)) names(listDF[[i]])[-1] <- todos[-length(listDF[[i]])] 
+0

Спасибо jogo, но почему он не меняет имена столбцов фрейма данных? Он только изменяет имена столбцов внутри списка, а не в независимом DF. – user3310782

+0

, но вы можете сделать 'listDF <- lapply (...)' – jogo

+0

Несомненно, но если вы хотите изменить имена столбцов DF, значит, это не путь? – user3310782