Извлечь имена столбцов data.frame из строк в data.frame

У меня есть пара data.frames, которые имеют примерно одинаковую структуру. Для воспроизводимого примера я создал два примера фреймов данных df1 и df2.

df1 <- structure(list(sample = c(2L, 6L), data1 = c(56L, 78L), data2 = c(59L, 
27L), data6 = c(90L, 28L), data1namet = structure(c(1L, 1L), .Label = "Sam1", class = "factor"), 
    data2namab = structure(c(1L, 1L), .Label = "Test2", class = "factor"), 
    dataame = structure(c(1L, 1L), .Label = "Ex3", class = "factor")), .Names = c("sample", 
"data1", "data2", "data3", "data1namet", "data2namab", "dataame"
), class = "data.frame", row.names = c(NA, -2L))

df1
  sample data1 data2 data3 data1namet data2namab dataame
1      2    56    59    90      Sam1     Test2       Ex3
2      6    78    27    28      Sam1     Test2       Ex3

df2 <- structure(list(sample = c(12L, 13L, 17L), data1 = c(56L, 78L, 
3L), data2 = c(59L, 27L, 2L), datest = structure(c(1L, 1L, 
1L), .Label = "Exa9", class = "factor"), dattestr = structure(c(1L, 
1L, 1L), .Label = "cz1", class = "factor")), .Names = c("sample", 
"data1", "data2", "datest", "dattestr"), class = "data.frame", row.names = c(NA, 
-3L))

df2
  sample data1 data2 datest dattestr
1     12   56   59      Exa9       cz1
2     13   78   27      Exa9       cz1
3     17    3    2      Exa9       cz1

Имя данных сохраняется в столбцах после столбцов данных, и мне было интересно, есть ли способ реструктурировать data.frames (около 40 data.frames), чтобы они содержали имя данных в имени столбца?

df1
  sample Sam1 Test2 Ex3
1      2   56    59  90
2      6   78    27  28

а также

df2
  sample Exa9 cz1
1     12   56  59
2     13   78  27
3     17    3   2

ИЗМЕНИТЬ

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

df1 <- structure(list(sample = c(2L, 6L), data1 = c(56L, 78L), data2 = c(59L, 
27L), data3 = c(90L, 28L), data1namet = structure(c(1L, 1L), .Label = "Sam1", class = "factor"), 
    data2namab = structure(c(1L, 1L), .Label = "Test2", class = "factor"), 
    dataame = structure(c(1L, 1L), .Label = "Ex3", class = "factor"), 
    ma = c("Jay", "Jay")), .Names = c("sample", "data1", "data2", 
"data3", "data1namet", "data2namab", "dataame", "ma"), row.names = c(NA, 
-2L), class = "data.frame")

df1
sample data1 data2 data3 data1namet data2namab dataame  ma
1      2    56    59    90       Sam1      Test2     Ex3 Jay
2      6    78    27    28       Sam1      Test2     Ex3 Jay

df2 <- structure(list(sample = c(12L, 13L, 17L), data1 = c(56L, 78L, 
3L), data2 = c(59L, 27L, 2L), datest = structure(c(1L, 1L, 1L
), .Label = "Exa9", class = "factor"), dattestr = structure(c(1L, 
1L, 1L), .Label = "cz1", class = "factor"), add = c(2, 2, 2)), .Names = c("sample", 
"data1", "data2", "datest", "dattestr", "add"), row.names = c(NA, 
-3L), class = "data.frame")

df2
sample data1 data2 datest dattestr add
1     12    56    59   Exa9      cz1   2
2     13    78    27   Exa9      cz1   2
3     17     3     2   Exa9      cz1   2

В этом случае столбцы ma и add не являются частью данных и должны быть добавлены в конце следующим образом:

df1
  sample Sam1 Test2 Ex3 ma
1      2   56    59  90 Jay
2      6   78    27  28 Jay

а также

df2
  sample Exa9 cz1 add
1     12   56  59 2
2     13   78  27 2
3     17    3   2 2

person nebuloso    schedule 10.07.2015    source источник
comment
Правильно ли я понимаю, что вы просто хотите удалить определенные столбцы, сохранив при этом остальную часть фрейма данных, включая имена столбцов?   -  person RHertel    schedule 10.07.2015
comment
почти. что я хочу сделать, так это извлечь эти имена столбцов из столбцов, которые будут удалены (столбцы, содержащие «имя» столбцов данных)   -  person nebuloso    schedule 10.07.2015


Ответы (2)


Можно начать с определения того, какие столбцы следует сохранить:

keep_col <- which(sapply(df2, is.numeric))

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

names <- df2[1,keep_col[-1] + length(keep_col)-1]
colnames(df2)[keep_col[-1]] <- as.character(unlist(names))

Наконец, фрейм данных можно собрать заново, сохранив только нужные столбцы:

df2 <- df2[,keep_col]
#> df2
#  sample Exa9 cz1
#1     12   56  59
#2     13   78  27
#3     17    3   2

Чтобы использовать это преобразование для нескольких разных фреймов данных, код можно обернуть в функцию:

summarize_table <- function(x){
 keep_col <- which(sapply(x, is.numeric))
 names <- x[1,keep_col[-1] + length(keep_col)-1] 
 colnames(x)[keep_col[-1]] <- as.character(unlist(names))
 x <- x[,keep_col]
}

Если различные кадры данных хранятся в списке, функцию summarize_table() можно использовать с lapply() для получения результатов для каждого кадра данных:

my_dfs <- list(df1,df2)
out <- lapply(my_dfs,summarize_table)
#> out
#[[1]]
#  sample Sam1 Test2 Ex3
#1      2   56    59  90
#2      6   78    27  28
#
#[[2]]
#  sample Exa9 cz1
#1     12   56  59
#2     13   78  27
#3     17    3   2

ИЗМЕНИТЬ/ДОБАВИТЬ

Модифицированная версия ниже должна иметь возможность обрабатывать также случаи, упомянутые в исправленном сообщении:

summarize_tab2 <- function(x){
 keep_col <- which(sapply(x, is.numeric))
 first_block <- c(keep_col[1],keep_col[which(diff(keep_col)==1)])
 add_col <- FALSE
 if (2 * (length(keep_col) - 1) + 1 < ncol(x)) add_col <- TRUE
 keep_col1 <- keep_col[1:length(first_block)]
 names <- x[1,keep_col1[-1] + length(keep_col1) - 1] 
 colnames(x)[keep_col1[-1]] <- as.character(unlist(names))
 df_t <- x[,keep_col]
 if (add_col) df_t <- cbind(df_t, x[(2 * (ncol(df_t) - 1) + 2):ncol(x)])
 return(df_t)
}
my_dfs <- list(df1, df2, df3, df4)
out <- lapply(my_dfs, summarize_tab2)
#> out
#[[1]]
#  sample Sam1 Test2 Ex3  ma
#1      2   56    59  90 Jay
#2      6   78    27  28 Jay
#
#[[2]]
#  sample Exa9 cz1 add
#1     12   56  59   2
#2     13   78  27   2
#3     17    3   2   2
#
#[[3]]
#  sample Sam1 Test2 Ex3
#1      2   56    59  90
#2      6   78    27  28
#
#[[4]]
#  sample Exa9 cz1
#1     12   56  59
#2     13   78  27
#3     17    3   2

Здесь кадры данных df3 и df4 — это, соответственно, кадры данных df1 и df2 исходного поста.

person RHertel    schedule 10.07.2015
comment
это выглядит великолепно, спасибо! Однако у меня есть около 40 различных data.frames. Как я могу применить это ко всем 40 кадрам данных? - person nebuloso; 10.07.2015
comment
Спасибо за ваши усилия! Однако я только что понял, что у меня есть дополнительные столбцы после частей «данные» и «имя данных» (я отредактировал вопрос с примерами данных, чтобы проиллюстрировать, что я имею в виду). Не могли бы вы взглянуть на это @RHertel? Спасибо. - person nebuloso; 11.07.2015

Следующее должно работать:

library(plyr)

cols.to.rename <- grep('^data(.)$', colnames(df1))
cols.of.names <- max(cols.to.rename)+seq(1,length(cols.to.rename))
the.names <- lapply(df1[1,cols.of.names], as.character)

df1.mod <- df1
colnames(df1.mod)[cols.to.rename] <- the.names
df1.mod <- df1.mod[-cols.of.names]

Он переименовывает все столбцы dataX в (первое) значение в столбцах, следующих за последним столбцом dataX. Затем он удаляет все столбцы имен из фрейма данных.

person Christoph Sommer    schedule 10.07.2015
comment
спасибо за ваш ответ @Christoph Sommer! Однако как я понимаю grep ищет одинаковые паттерны. Однако в моих данных имена столбцов не всегда совпадают, поэтому это не работает. Он меняется с data.frame на data.frame, и у меня есть около 40 data.frames, которые я хотел бы изменить. Это было нечетко сформулировано с моей стороны, извините (я изменил свои образцы данных, чтобы сделать это более понятным). - person nebuloso; 10.07.2015
comment
Я понимаю. Это оставляет совершенно неясными две вещи: во-первых, как в ваших таблицах отличить столбцы, содержащие данные, от столбцов, содержащих имена? Во-вторых, как узнать, что кому принадлежит? - person Christoph Sommer; 10.07.2015
comment
Мне удалось организовать данные таким образом, что столбцы данных пронумерованы. Таким образом, данные1, данные2 и данные3 для первого df являются «столбцами данных», а затем следуют 3 «столбца имен данных». надеюсь так понятнее? - person nebuloso; 10.07.2015
comment
Справедливо. Я изменил ответ соответственно - person Christoph Sommer; 10.07.2015