如何使用R自动重命名宽数据中的列

如何使用R自动重命名宽数据中的列,r,dataframe,rename,mutate,R,Dataframe,Rename,Mutate,以宽幅格式考虑以下数据 df<-data.frame("id"=c(1,2,3,4), "ex"=c(1,0,0,1), "aQL"=c(5,4,NA,6), "bQL"=c(5,7,NA,9), "cQL"=c(5,7,NA,9), "bST"=c(3,7,8,

以宽幅格式考虑以下数据

df<-data.frame("id"=c(1,2,3,4),
           "ex"=c(1,0,0,1),
           "aQL"=c(5,4,NA,6),
           "bQL"=c(5,7,NA,9),
           "cQL"=c(5,7,NA,9),
           "bST"=c(3,7,8,9),
           "cST"=c(8,7,5,3),
           "aXY"=c(1,9,4,4),
           "cXY"=c(5,3,1,4))
主数据集有许多变量,因此我希望重命名以自动方式完成。我尝试了以下代码

renameCol <- function(x) {
setNames(x, paste0("QL.", seq_len(ncol(x))))
}
renameCol(df)

renameCol这是一个通过
stringr
包使用正则表达式的解决方案:

库(stringr)

df我建议一种不需要函数的
tidyverse
方法。在此解决方案中,您可以提取每个变量名称的第一个字母作为id,然后使用
cur\u group\u id
分配一个数字,以便保持顺序。最后,使用这个新数字转换包含名称的变量,然后格式化为wide,以获得预期的输出:

library(tidyverse)
#Data
df<-data.frame("id"=c(1,2,3,4),
               "ex"=c(1,0,0,1),
               "aQL"=c(5,4,NA,6),
               "bQL"=c(5,7,NA,9),
               "cQL"=c(5,7,NA,9),
               "bST"=c(3,7,8,9),
               "cST"=c(8,7,5,3),
               "aXY"=c(1,9,4,4),
               "cXY"=c(5,3,1,4))
#Reshape
df %>% pivot_longer(cols = -c(1,2)) %>%
  #Extract first letter as id
  mutate(id2=substring(name,1,1)) %>%
  #Create the number id
  group_by(id2) %>%
  mutate(id3=cur_group_id()) %>%
  #Clean name
  mutate(name=substring(name,2,nchar(name))) %>%
  #Create final var
  mutate(name2=paste0(name,'.',id3)) %>% ungroup() %>%
  dplyr::select(-c(name,id2,id3)) %>%
  #Format to wide
  pivot_wider(names_from = name2,values_from=value)
库(tidyverse)
#资料
df%pivot_更长(cols=-c(1,2))%>%
#提取第一个字母作为id
突变(id2=子字符串(名称,1,1))%>%
#创建数字标识
分组依据(id2)%>%
突变(id3=cur_group_id())%>%
#干净的名字
突变(名称=子字符串(名称,2,nchar(名称)))%>%
#创建最终变量
mutate(name2=paste0(name,'.',id3))%%>%ungroup()%%>%
dplyr::select(-c(名称,id2,id3))%>%
#格式要宽
枢轴(名称从=name2,值从=value)
输出:

# A tibble: 4 x 9
     id    ex  QL.1  QL.2  QL.3  ST.2  ST.3  XY.1  XY.3
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     1     1     5     5     5     3     8     1     5
2     2     0     4     7     7     7     7     9     3
3     3     0    NA    NA    NA     8     5     4     1
4     4     1     6     9     9     9     3     4     4
#一个tible:4 x 9
id ex QL.1 QL.2 QL.3 ST.2 ST.3 XY.1 XY.3
1     1     1     5     5     5     3     8     1     5
2     2     0     4     7     7     7     7     9     3
3 3 0 NA NA 8 5 4 1
4     4     1     6     9     9     9     3     4     4

您可以尝试的另一种方法

colnames(df)[grepl("QL", colnames(df))] <- str_c("QL.", 1:3)

colnames(df)[grepl("ST", colnames(df))] <- str_c("ST.", 2:3)

colnames(df)[grepl("XY", colnames(df))] <- str_c("XY.", c(1,3))

#   id ex QL.1 QL.2 QL.3 ST.2 ST.3 XY.1 XY.3
# 1  1  1    5    5    5    3    8    1    5
# 2  2  0    4    7    7    7    7    9    3
# 3  3  0   NA   NA   NA    8    5    4    1
# 4  4  1    6    9    9    9    3    4    4

colnames(df)[grepl(“QL”,colnames(df))]使用基本模式匹配:

您需要定义一个函数,该函数在单个列名上执行所需的操作:

f = function(x){
  beg <- str_extract(x,"[a-z](?=[A-Z]{2})")
  num <- which(letters == beg)
  output <- paste0(str_extract(x,"(?<=[a-z])[A-Z]{2}"),".",num)
  return(output)
}
然后,您可以直接在数据帧的名称上使用
regmatches
和正则表达式:

m <- gregexpr("[a-z][A-Z]{2}", names(df),perl = T)
regmatches(names(df), m) <- lapply(regmatches(names(df), m), f)
names(df)

> names(df)
[1] "id"   "ex"   "QL.1" "QL.2" "QL.3" "ST.2" "ST.3" "XY.1" "XY.3"

m在基本R中,您可以执行以下操作:

names(df) <- sub("(\\d)([A-Z]{2})$","\\2.\\1", chartr("abc","123",names(df)))
 df
  id ex QL.1 QL.2 QL.3 ST.2 ST.3 XY.1 XY.3
1  1  1    5    5    5    3    8    1    5
2  2  0    4    7    7    7    7    9    3
3  3  0   NA   NA   NA    8    5    4    1
4  4  1    6    9    9    9    3    4    4

names(df)谢谢!这里有些秩序。变量的前缀a、b、c的顺序为.1、.2、.3。是否可以将“bST”和“cXY”重新编码为ST.2和XY.3?谢谢!你能解释一下改名的工作原理吗?e、 g.如果你考虑改名为a.QL、b.QL、c.QL、a.ST、e.t.c.@TRichard这里发生的事情是
chartr
abc
更改为
123
等尝试
chartr(“abcde”,“12345”,“你是我的国王”)
你会注意到
aeiou
已分别更改为
12345
。然后使用
sub
捕获一个
\\d
(数字),后跟
[a-Z]{2}
2个大写字母,并在两个组之间放置一个点,同时切换捕获组的顺序。即尝试执行
sub(\\d)([a-Z]{2}),“\\2-\\1”,“2DR”)
m <- gregexpr("[a-z][A-Z]{2}", names(df),perl = T)
regmatches(names(df), m) <- lapply(regmatches(names(df), m), f)
names(df)

> names(df)
[1] "id"   "ex"   "QL.1" "QL.2" "QL.3" "ST.2" "ST.3" "XY.1" "XY.3"
names(df) <- sub("(\\d)([A-Z]{2})$","\\2.\\1", chartr("abc","123",names(df)))
 df
  id ex QL.1 QL.2 QL.3 ST.2 ST.3 XY.1 XY.3
1  1  1    5    5    5    3    8    1    5
2  2  0    4    7    7    7    7    9    3
3  3  0   NA   NA   NA    8    5    4    1
4  4  1    6    9    9    9    3    4    4
names(df) <- sub("(\\d)([A-Z]{2})$","\\2.\\1", chartr("abc","123",names(df)))
a <- read.table(text=grep("\\.\\d",names(df),value = TRUE), sep=".")
b <- subset(aggregate(.~V1, a, function(x) setdiff(1:3,x)), V2>0)
df[do.call(paste, c(sep = ".", b))] <- NA
(df1 <- df[c(1, 2, order(names(df)[-(1:2)]) + 2)])

  id ex QL.1 QL.2 QL.3 ST.1 ST.2 ST.3 XY.1 XY.2 XY.3
1  1  1    5    5    5   NA    3    8    1   NA    5
2  2  0    4    7    7   NA    7    7    9   NA    3
3  3  0   NA   NA   NA   NA    8    5    4   NA    1
4  4  1    6    9    9   NA    9    3    4   NA    4