Как изменить имена столбцов в нескольких фреймах данных с помощью файла сопоставления в R? - PullRequest
2 голосов
/ 16 июня 2020

У меня есть сценарий, который просматривает данные за несколько лет, по одному году за раз. Данные за каждый год состоят из нескольких фреймов данных, которые помещаются в список под названием all_input. В начале l oop (после считывания данных) я пытаюсь получить данные за все годы в том же формате до остальной обработки.

Проблема, в которой я имеет с именами столбцов, которые не являются единообразными. В каждый фрейм данных, которые я хочу сохранить, включены 5 столбцов, и я хочу, чтобы они назывались total_emissions uom tribal_name st_usps_cd и description. В некоторых фреймах данных у них уже есть эти имена, в то время как в других у них есть разные имена, например pollutant.desc или pollutant_desc.

Мой текущий подход таков:

# Create a mapping file for the column names
    header_map <- data.frame(orignal_col = c( "pollutant_desc", "pollutant.desc", "emissions.uom", "total.emissions", "tribal.name", "state" ), 
                               new_col = c( "description", "description", "uom", "total_emissions", "tribal_name", "st_usps_cd" ), stringsAsFactors = FALSE)

    # change the column names
    lapply(all_input, function(x) {
      names(x)[match(header_map$orignal_col, names(x))] <- header_map$new_col
      x
    }) -> all_input

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

original_col         new_col
pollutant_desc       description
pollutant.desc       description
emissions.uom        uom
total.emissions      total_emissions
tribal.name          tribal_name
state                st_usps_cd

Я получаю следующую ошибку:

Error in names(x)[match(header_map$orignal_col, names(x))] <- header_map$new_col : 
  NAs are not allowed in subscripted assignments

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

Fake Sample Data. df1 и df2 представляют формат данных «2017», где несколько столбцов требуют изменения имен, но текущие имена согласованы между фреймами данных. df3 представляет данные "2011", где все имена столбцов такие, какими они должны быть. df4 представляет данные «2014», где единственный столбец, который необходимо изменить, - это pollutant_desc. Обратите внимание: в каждом фрейме данных есть дополнительные столбцы, которые не нужны и их можно игнорировать. Напоминаем, что не все фреймы данных читаются одновременно. L oop по году, поэтому df1 и df2 (в списке all_input) будут отформатированы и обработаны. Затем все данные удаляются, и создается новый список all_input с фреймами данных следующих лет, которые будут иметь другие имена столбцов. Код должен работать все годы без изменений.

> dput(df1)
structure(list(total.emissions = structure(1:2, .Label = c("100", 
"300"), class = "factor"), emissions.uom = structure(1:2, .Label = c("LB", 
"TON"), class = "factor"), international = c(TRUE, TRUE), hours = structure(2:1, .Label = c("17", 
"3"), class = "factor"), tribal.name = structure(2:1, .Label = c("FLLK", 
"SUWJG"), class = "factor"), state = structure(1:2, .Label = c("AK", 
"MN"), class = "factor"), pollutant.desc = structure(1:2, .Label = c("Methane", 
"NO2"), class = "factor"), policy = c(TRUE, FALSE)), class = "data.frame", row.names = c(NA, 
-2L))
> dput(df2)
structure(list(total.emissions = structure(2:1, .Label = c("20", 
"400"), class = "factor"), emissions.uom = structure(c(1L, 1L
), .Label = "TON", class = "factor"), international = c(FALSE, 
TRUE), hours = structure(2:1, .Label = c("1", "8"), class = "factor"), 
    tribal.name = structure(2:1, .Label = c("SOSD", "WMFJU"), class = "factor"), 
    state = structure(2:1, .Label = c("SD", "WY"), class = "factor"), 
    pollutant.desc = structure(1:2, .Label = c("CO2", "SO2"), class = "factor"), 
    policy = c(FALSE, FALSE)), class = "data.frame", row.names = c(NA, 
-2L))
> dput(df3)
structure(list(total_emissions = structure(2:1, .Label = c("200", 
"30"), class = "factor"), uom = structure(c(1L, 1L), .Label = "TON", class = "factor"), 
    boundaries = structure(2:1, .Label = c("N", "Y"), class = "factor"), 
    tribal_name = structure(2:1, .Label = c("SOSD", "WMFJU"), class = "factor"), 
    st_usps_cd = structure(2:1, .Label = c("ID", "KS"), class = "factor"), 
    description = structure(c(1L, 1L), .Label = "SO2", class = "factor"), 
    policy = c(FALSE, TRUE), time = structure(1:2, .Label = c("17", 
    "7"), class = "factor")), class = "data.frame", row.names = c(NA, 
-2L))
> dput(df4)
structure(list(total_emissions = structure(2:1, .Label = c("700", 
"75"), class = "factor"), uom = structure(c(1L, 1L), .Label = "LB", class = "factor"), 
    tribal_name = structure(1:2, .Label = c("SSJY", "WNCOPS"), class = "factor"), 
    st_usps_cd = structure(1:2, .Label = c("MO", "NY"), class = "factor"), 
    pollutant_desc = structure(2:1, .Label = c("CO2", "Methane"
    ), class = "factor"), boundaries = structure(c(1L, 1L), .Label = "N", class = "factor"), 
    policy = c(FALSE, FALSE), time = structure(1:2, .Label = c("2", 
    "3"), class = "factor")), class = "data.frame", row.names = c(NA, 
-2L))

Спасибо!

1 Ответ

2 голосов
/ 16 июня 2020

Попробуйте следующее:

list_of_frames1 <- list(df1, df2, df3, df4)
list_of_frames2 <- lapply(list_of_frames1, function(x) {
  nms <- intersect(names(x), header_map$orignal_col)
  names(x)[ match(nms, names(x)) ] <- header_map$new_col[ match(nms, header_map$orignal_col) ]
  x
})
...