Извлечение символов и переименование столбцов в R

Я новичок в R. Я экспортировал данные из базы данных и пытаюсь переименовать столбцы.

Примеры существующих названий (по одному объекту на параметр качества воды) приведены ниже в кавычках. Есть 6 возможных параметров на каждом сайте и 40 сайтов; Я хотел бы переименовать столбцы на основе параметра и сайта. Названия сайтов состоят из 3-7 символов и всегда идут после последней запятой. В моем наборе данных (AQexport1) 240 столбцов и 47 714 строк (строки представляют собой метки времени ежечасных непрерывных данных). Я хочу иметь возможность использовать код для других экспортов из этой базы данных с тем же форматом и параметрами, но, возможно, с другими сайтами.

Например:

  1. "Темп.Воды.Темп.Воды.БУБУ" | "Темп.Воды.Температура.BUBU" ‹--- Темп.BUBU
  2. "Вода.Темп.Поля.Посещения.KNF_DUP" ‹--- FVTemp.KNF_DUP
  3. "Sp.Cond.TempCorrected_nodrift.LOD_DUP" ‹---SpCnd.LOD_Dup
  4. "Sp.Cond.TempCorrected.PFM" ‹--- SpC.PFM
  5. "Sp.Cond.Field.Visits.CC7" ‹-- FVSpC.CC7
  6. "Cond.Conductivity.TM02Dup"‹-- Cond.TM02Dup

Я не могу понять, как написать contains() в операторе if (я понимаю, что приведенный ниже синтаксис неверен, я просто пытаюсь показать, что я думаю) или как извлечь символы из строки с несколькими десятичными знаками. точки, и это не извлекает одинаковое количество символов из конца имени столбца. Мне также интересно, является ли цикл for через colnames() лучшим решением.

for (i in 1:colnames(AQexport1)){
  if (colnames(AQexport1[i]) contains "Water.Temp.W" | "Water.Temp.T"){
    colnames(AQexport1[i]) <- Temp.insert_site_name_here
  } 
    elseif (colnames(AQexport1[i])) contains "Water.Temp.F") {
      colnames(AQexport1[i]) <- FVTemp.insert_site_name_here
    }
    elseif (colnames(AQexport1[i])) contains "nodrift") {
      colnames(AQexport1[i])<-SpCnd.insert_site_name_here
    }
    elseif (colnames((AQexport1[i])) contains "Sp.Cond.T") {
      colnames(AQexport1[i])<-SpC.insert_site_name_here
    }
#continue elseif statements
} 

person Ecologist711    schedule 07.03.2017    source источник
comment
Обратите внимание на это обсуждение и сделайте свой пост воспроизводимым. Я думаю, вы ищете %in% как в: c("a", "b") %in% c("a", 45). Ваш код не кажется синтаксически правильным, contains при условии, что это будет относиться к объекту contains, есть и другие странные вещи, то, что AQexport1, AQexport1[i] имеет смысл, если AQexport1 является вектором, но я, вроде как, думаю, в контексте ваш код AQexport1 соответствует каким-то данным?   -  person Konrad    schedule 07.03.2017
comment
В контексте переименования столбцов вы можете: names(mtcars)[names(mtcars) %in% c("mpg", "cyl")] <- c("renameThisColumn")   -  person Konrad    schedule 07.03.2017
comment
Спасибо Конрад за ссылку. Обязательно упомяну об этом в будущих постах. Я знал, что colnames создает вектор, который я мог бы индексировать, но, как вы указали, я ошибочно подумал, что могу заменить значение в этом векторе, чтобы изменить имена столбцов в моем фрейме данных.   -  person Ecologist711    schedule 07.03.2017
comment
Ваше решение по переименованию работает. Однако, имея 240 уникальных имен столбцов, которые нужно изменить, и имена столбцов, которые могут меняться в зависимости от того, что я экспортирую из своей базы данных, я надеялся найти решение, в котором мне не нужно было бы вводить каждое имя. Если я использую функцию substring() для создания новых имен, решение Райана должно работать.   -  person Ecologist711    schedule 07.03.2017


Ответы (2)


В упрощенном случае это то, как вы переназначаете имена в зависимости от того, содержат ли они буквы «a» или «b», или содержат «c» или «d» и так далее.

dat <- data.frame(aa = runif(10), ba = runif(10), ct = runif(10), df = runif(10), en = runif(10), zz = runif(10))

names(dat)
##  "aa" "ba" "ct" "df" "en" "zz"

library(magrittr)

# logical, TRUE if names contain a or b
condition1 <- sapply(c('a','b'), grepl, names(dat)) %>% rowSums %>% as.logical

# logical, TRUE if names contain c or d
condition2 <- sapply(c('c','d'), grepl, names(dat)) %>% rowSums %>% as.logical

# logical, TRUE if names contain e
condition3 <- grepl('e', names(dat))



names(dat) <- ifelse(condition1, 'newname1',
              ifelse(condition2, 'newname2',
              ifelse(condition3, 'newname3', 
                                 'newname4')))

names(dat)
## [1] "newname1" "newname1" "newname2" "newname2" "newname3" "newname4"
person Ryan    schedule 07.03.2017
comment
Спасибо, очень полезно! Я забыл, что логические числа могут быть преобразованы в 1 или 0 и обратно. И я буду использовать substring() для создания правильных новых имен. - person Ecologist711; 07.03.2017

AQexport 1 — это мой набор данных, которому нужны новые имена столбцов. Это было моим решением.

# 6 parameters with 11 syntax's to change column names for (each syntax could have up to 40 variations (.site names):
# "Water.Temp.Water.Temp.BUBU" or 
# "Water.Temp.Temperature.BUBU" or
# "Water.Temp.Temp.BUBU"<--- Temp.BUBU
# "Water.Temp.Field.Visits.KNF_DUP" <--- FVTemp.KNF_DUP
# "Sp.Cond.Sp.Cond.TempCorrected_nodrift.DRBR" or 
# "Sp.Cond.Sp.Cond..TempCorrected_nodrift.BRCD" or 
# "Sp.Cond.SpCond.nodrift.TM01" or
# "Sp.Cond.TempCorrected_nodrift.LOD_DUP" <---SpCnd.site
# "Sp.Cond.TempCorrected.PFM" <--- SpC.PFM
# "Sp.Cond.Field.Visits.CC7" <-- FVSpC.CC7
# "Cond.Conductivity.TM02Dup"<-- Cond.TM02Dup
# nchar("Sp.Cond.TempCorrected_nodrift.DRBR") #number of characters in string

#logical vectors, TRUE if AQexport1 column names match charcter input in grepl
Names<-names(AQexport1)
Temp.siteW<-grepl("Water.Temp.Water.Temp", Names)
Temp.siteT<-grepl("Water.Temp.Temperature", Names)
Temp.siteTT<-grepl("Water.Temp.Temp", Names)
FVTemp.site<-grepl("Temp.Field", Names)
FVSpC.site<-grepl("Sp.Cond.Field", Names)
SpCnd.site1<-grepl("Sp.Cond.Sp.Cond.TempCorrected_nodrift.", Names)
SpCnd.site2<-grepl("Sp.Cond.Sp.Cond..TempCorrected_nodrift..", Names)
SpCnd.site3<-grepl("Sp.Cond.SpCond.nodrift.", Names)
SpCnd.site4<-grepl("Sp.Cond.TempCorrected_nodrift.", Names)
Cond.site<-grepl("Cond.C", Names)
SpC.site<-grepl("Sp.Cond.TempCorrected.", Names) #Sp.Cond.TempCorrected.  the last period is critical to distinguish from nodrift

#Creating new column name: Paste parameter prefix to site name (extracted  from old column name with substring)
#Making parameter always 4 characters
Temp.namesW<-paste("Temp.",substring(Names,23), sep="")
Temp.namesT<-paste("Temp.",substring(Names,24), sep="")
Temp.namesTT<-paste("Temp.",substring(Names,17), sep="")
FVTemp.names<-paste("FTem.",substring(Names,25), sep="")
FVSpC.names<-paste("FSpC.",substring(Names,22), sep="")
SpCnd.names1<-paste("SCnd.",substring(Names,39), sep="")
SpCnd.names2<-paste("SCnd.",substring(Names,40), sep="")
SpCnd.names3<-paste("SCnd.",substring(Names,24), sep="")
SpCnd.names4<-paste("SCnd.",substring(Names,31), sep="")
Cond.names<-paste("Cond.",substring(Names,19), sep="")
SpC.names<-paste("SpCc.",substring(Names,23), sep="")

for (i in 1:ncol(AQexport1)){
  if(Temp.siteW[i]){
    names(AQexport1)[i]<-Temp.namesW[i]
  }
  else if(Temp.siteT[i]){
  names(AQexport1)[i]<-Temp.namesT[i]
  }
  else if(Temp.siteTT[i]){
    names(AQexport1)[i]<-Temp.namesTT[i]
  }
  else if(FVTemp.site[i]){
  names(AQexport1)[i]<-FVTemp.names[i]
  }
  else if(FVSpC.site[i]){
    names(AQexport1)[i]<-FVSpC.names[i]
  }
  else if(SpCnd.site1[i]){
    names(AQexport1)[i]<-SpCnd.names1[i]
  }
  else if(SpCnd.site2[i]){
    names(AQexport1)[i]<-SpCnd.names2[i]
  }
  else if(SpCnd.site3[i]){
    names(AQexport1)[i]<-SpCnd.names3[i]
  }
  else if(SpCnd.site4[i]){
    names(AQexport1)[i]<-SpCnd.names4[i]
  }
  else if(Cond.site[i]){
    names(AQexport1)[i]<-Cond.names[i]
  }
  else if(SpC.site[i]){
    names(AQexport1)[i]<-SpC.names[i]
  }
}
person Ecologist711    schedule 09.03.2017