source

이름으로 여러 열 이름 바꾸기

nicesource 2023. 6. 28. 21:49
반응형

이름으로 여러 열 이름 바꾸기

누군가 이미 물어봤어야 했는데, 답을 찾을 수가 없었어요.내가 가지고 있다고 말하시오:

x = data.frame(q=1,w=2,e=3, ...and many many columns...)  

위치를 몰라도 되는 임의의 열의 하위 집합을 다른 임의의 이름으로 바꾸는 가장 우아한 방법은 무엇입니까?

예: 이름을 바꾸고 싶다고 말합니다."q"그리고."e"안으로"A"그리고."B"이것을 하기 위한 가장 우아한 코드는 무엇입니까?

분명히, 저는 루프를 할 수 있습니다.

oldnames = c("q","e")
newnames = c("A","B")
for(i in 1:2) names(x)[names(x) == oldnames[i]] = newnames[i]

하지만 더 좋은 방법이 있을까요?패키지를 좀 사용하는 게 어때요?(plyr::rename아래)

dplyr을 사용하면 다음 작업을 수행할 수 있습니다.

library(dplyr)

df = data.frame(q = 1, w = 2, e = 3)
    
df %>% rename(A = q, B = e)

#  A w B
#1 1 2 3

또는 @Jelena-bioinf가 제안한 것처럼 벡터를 사용하고자 하는 경우:

library(dplyr)

df = data.frame(q = 1, w = 2, e = 3)

oldnames = c("q","e")
newnames = c("A","B")

df %>% rename_at(vars(oldnames), ~ newnames)

#  A w B
#1 1 2 3

L. D. 니콜라스 메이는 주어진 변화를 제안했습니다.rename_at에 의해 .rename_with:

df %>% 
  rename_with(~ newnames[which(oldnames == .x)], .cols = oldnames)

#  A w B
#1 1 2 3

setnamesdata.table는 패지작니다에서 할 것입니다.data.frame상심한data.tables

library(data.table)
d <- data.frame(a=1:2,b=2:3,d=4:5)
setnames(d, old = c('a','d'), new = c('anew','dnew'))
d


 #   anew b dnew
 # 1    1 2    4
 # 2    2 3    5

참조를 통해 변경되므로 복사할 필요가 없습니다(data.frames의 경우에도!).

너무 크지 않은 데이터 프레임을 위한 또 다른 솔루션은 다음과 같습니다(@latemail 응답 기반).

x <- data.frame(q=1,w=2,e=3)

> x
  q w e
1 1 2 3

colnames(x) <- c("A","w","B")

> x
  A w B
1 1 2 3

또는 다음을 사용할 수도 있습니다.

names(x) <- c("C","w","D")

> x
  C w D
1 1 2 3

또한 열 이름의 하위 집합 이름을 변경할 수도 있습니다.

names(x)[2:3] <- c("E","F")

> x
  C E F
1 1 2 3

여러 열의 이름을 다음과 같이 조합하여 변경하는 가장 효율적인 방법은 다음과 같습니다.purrr::set_names()그리고 몇 개stringr작전

library(tidyverse)

# Make a tibble with bad names
data <- tibble(
    `Bad NameS 1` = letters[1:10],
    `bAd NameS 2` = rnorm(10)
)

data 
# A tibble: 10 x 2
   `Bad NameS 1` `bAd NameS 2`
   <chr>                 <dbl>
 1 a                    -0.840
 2 b                    -1.56 
 3 c                    -0.625
 4 d                     0.506
 5 e                    -1.52 
 6 f                    -0.212
 7 g                    -1.50 
 8 h                    -1.53 
 9 i                     0.420
 10 j                     0.957

# Use purrr::set_names() with annonymous function of stringr operations
data %>%
    set_names(~ str_to_lower(.) %>%
                  str_replace_all(" ", "_") %>%
                  str_replace_all("bad", "good"))

# A tibble: 10 x 2
   good_names_1 good_names_2
   <chr>               <dbl>
 1 a                  -0.840
 2 b                  -1.56 
 3 c                  -0.625
 4 d                   0.506
 5 e                  -1.52 
 6 f                  -0.212
 7 g                  -1.50 
 8 h                  -1.53 
 9 i                   0.420
10 j                   0.957

dplyr 1.0.0 업데이트

최신 dplyr 버전은 다음을 추가하여 더욱 유연해졌습니다.rename_with()_with 함수를 입력이라고 합니다.요령은 문자 벡터를 재구성하는 것입니다.newnames~ , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , .function(x) return (newnames).

제 주관적인 생각으로는, 그것이 가장 우아한 dplyr 표현입니다.는 @desval: @desval로 묶어야 .all_of모든 요소를 포함합니다.

# shortest & most elegant expression
df %>% rename_with(~ newnames, all_of(oldnames))

A w B
1 1 2 3

참고 사항:

순서를 반대로 할 경우 .fn 인수를 .cols 인수 앞에 .fn이 필요합니다.

df %>% rename_with(oldnames, .fn = ~ newnames)

A w B
1 1 2 3

또는 .col 인수를 지정합니다.

 df %>% rename_with(.col = oldnames, ~ newnames)

A w B
1 1 2 3

그래서 최근에 열이 존재하는지 확실하지 않고 다음과 같은 이름만 변경하려는 경우 이 문제를 직접 경험했습니다.

existing <- match(oldNames,names(x))
names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))]

@user314046의 답변을 기반으로 구축:

x <- data.frame(q=1,w=2,e=3)
x
#  q w e
#1 1 2 3

names(x)[match(oldnames, names(x))] <- newnames

x
#  A w B
#1 1 2 3

은 은것다특정열의않지다습의 열 x데이터 집합입니다.

명명된 벡터를 사용할 수 있습니다.두 가지 옵션(기본 R 및 dplyr 포함) 아래에 있습니다.

기본 R, 부분 집합을 통해:

x = data.frame(q = 1, w = 2, e = 3) 

rename_vec <- c(q = "A", e = "B")
## vector of same length as names(x) which returns NA if there is no match to names(x)
which_rename <- rename_vec[names(x)]
## simple ifelse where names(x) will be renamed for every non-NA 
names(x) <- ifelse(is.na(which_rename), names(x), which_rename)

x
#>   A w B
#> 1 1 2 3

라오.dplyr할 수 있습니다.!!!:

library(dplyr)

rename_vec <- c(A = "q", B = "e") # the names are just the other way round than in the base R way!

x %>% rename(!!!rename_vec)
#>   A w B
#> 1 1 2 3

후자는 '빅뱅' 연산자 때문에 작동합니다.!!!목록 또는 벡터를 강제로 평가하는 것입니다.

?`!!`

개체 목록을 강제로 분할합니다.목록의 요소는 제자리에 결합되어 있으며, 이는 각 요소가 하나의 단일 인수가 된다는 것을 의미합니다.

names(x)[names(x) %in% c("q","e")]<-c("A","B")

기능을 언급하는 몇 가지 답변이 있습니다.dplyr::rename_with그리고.rlang::set_names되어 있습니다. 을 바꾸기 함수와 .이 대답은 열 이름을 바꾸기 위해 함수와 공식을 사용하는 것과 둘 사이의 차이를 보여줍니다.

rename_withdplyr한 열의 을 "" " " " " " " " " " " 로 된 열 이름을 바꿀 수 ..cols를 들어, 함수명같이,toupper:

library(dplyr)
rename_with(head(iris), toupper, starts_with("Petal"))

하는 것과 .~ toupper(.x):

rename_with(head(iris), ~ toupper(.x), starts_with("Petal"))

열의 을 바꿀 는 모열의이변때다사수있다용습니도할을 사용할 수도 .set_names랑그 패키지에서.예를 , 른다예들면자를,면들자를을 해 보겠습니다paste0이름 바꾸기 기능으로 사용할 수 있습니다. pasteO두 개의 인수를 사용하므로 함수를 사용하는지 공식을 사용하는지에 따라 두 번째 인수를 전달하는 방법이 달라집니다.

rlang::set_names(head(iris), paste0, "_hi")
rlang::set_names(head(iris), ~ paste0(.x, "_hi"))

다음과 같은 작업을 수행할 수 있습니다.rename_with을 첫 인수로 으로써 첫 번 인 로 터 프 을 임 으 함 로 전 달 써 레 이 데 째 수 ▁by 첫 으 로 ▁the 함 써 ▁frame.data는 다음과 같습니다..fn 열을 세 인수로 합니다..cols=everything()네 인수인 변수는 ....또는 두 번째, 세 번째 및 네 번째 인수를 두 번째 인수로 지정된 공식에 배치할 수 있습니다.

rename_with(head(iris), paste0, everything(), "_hi")
rename_with(head(iris), ~ paste0(.x, "_hi"))

rename_with데이터 프레임에서만 작동합니다. set_names 변경을 .

rlang::set_names(1:4, c("a", "b", "c", "d"))

이렇게 하면 모든 이름에 나타나는 모든 문자가 변경됩니다.

 names(x) <- gsub("q", "A", gsub("e", "B", names(x) ) )

이름 집합을 가져와 목록으로 저장한 다음 문자열에서 대량 이름 변경을 수행할 수 있습니다.데이터셋을 전체적으로 길게 전환하는 경우를 예로 들 수 있습니다.

names(labWide)
      Lab1    Lab10    Lab11    Lab12    Lab13    Lab14    Lab15    Lab16
1 35.75366 22.79493 30.32075 34.25637 30.66477 32.04059 24.46663 22.53063

nameVec <- names(labWide)
nameVec <- gsub("Lab","LabLat",nameVec)

names(labWide) <- nameVec
"LabLat1"  "LabLat10" "LabLat11" "LabLat12" "LabLat13" "LabLat14""LabLat15"    "LabLat16" " 

테이블에 이름이 같은 두 개의 열이 포함되어 있으면 코드는 다음과 같습니다.

rename(df,newname=oldname.x,newname=oldname.y)

참고로 문자열 하나를 모든 열 이름에 연결하려면 이 단순 코드를 사용하면 됩니다.

colnames(df) <- paste("renamed_",colnames(df),sep="")

롯은 일종의 답이기 때문에 복사/붙여넣기가 가능하도록 함수를 작성했습니다.

rename <- function(x, old_names, new_names) {
    stopifnot(length(old_names) == length(new_names))
    # pull out the names that are actually in x
    old_nms <- old_names[old_names %in% names(x)]
    new_nms <- new_names[old_names %in% names(x)]

    # call out the column names that don't exist
    not_nms <- setdiff(old_names, old_nms)
    if(length(not_nms) > 0) {
        msg <- paste(paste(not_nms, collapse = ", "), 
            "are not columns in the dataframe, so won't be renamed.")
        warning(msg)
    }

    # rename
    names(x)[names(x) %in% old_nms] <- new_nms
    x
}

 x = data.frame(q = 1, w = 2, e = 3)
 rename(x, c("q", "e"), c("Q", "E"))

   Q w E
 1 1 2 3

데이터의 한 행에 모든 열을 변경하려는 이름이 포함된 경우 다음과 같이 할 수 있습니다.

names(data) <- data[row,]

해진정data이며 "데이터 프레임"입니다.row새 값이 들어 있는 행 번호입니다.

그런 다음 이름이 포함된 행을 제거할 수 있습니다.

data <- data[-row,]

다음 기능이 필요합니다.그런 다음 이름 바꾸기(X)에 x를 전달하면 나타나는 모든 값의 이름이 바뀌고 해당 값이 없으면 오류가 발생하지 않습니다.

rename <-function(x){
  oldNames = c("a","b","c")
  newNames = c("d","e","f")
  existing <- match(oldNames,names(x))
  names(x)[na.omit(existing)] <- newNames[which(!is.na(existing))]
  return(x)
}

전문 패키지를 사용하는 위의 많은 좋은 답변.이것은 기본 R로만 수행하는 간단한 방법입니다.

df.rename.cols <- function(df, col2.list) {
  tlist <- transpose(col2.list)
    
  names(df)[which(names(df) %in% tlist[[1]])] <- tlist[[2]]

  df
} 

다음은 예입니다.

df1 <- data.frame(A = c(1, 2), B = c(3, 4), C = c(5, 6), D = c(7, 8))
col.list <- list(c("A", "NewA"), c("C", "NewC"))
df.rename.cols(df1, col.list)

  NewA B NewC D
1    1 3    5 7
2    2 4    6 8

저는 최근에 @agile bean의 답변으로 구축했습니다(사용).rename_with의 전에종rename_at)를사용하여 프레임에 하는 열 열시킬 수 있습니다 데이터 프레임에 열 이름이 있는 경우 이를 변경하는 함수를 구축하여, 해당하는 경우 이종 데이터 프레임의 열 이름을 서로 일치시킬 수 있습니다.

루프는 확실히 개선될 수 있지만, 저는 후손들을 위해 공유할 것이라고 생각했습니다.

예제 데이터 프레임 생성:
x= structure(list(observation_date = structure(c(18526L, 18784L, 
17601L), class = c("IDate", "Date")), year = c(2020L, 2021L, 
2018L)), sf_column = "geometry", agr = structure(c(id = NA_integer_, 
common_name = NA_integer_, scientific_name = NA_integer_, observation_count = NA_integer_, 
country = NA_integer_, country_code = NA_integer_, state = NA_integer_, 
state_code = NA_integer_, county = NA_integer_, county_code = NA_integer_, 
observation_date = NA_integer_, time_observations_started = NA_integer_, 
observer_id = NA_integer_, sampling_event_identifier = NA_integer_, 
protocol_type = NA_integer_, protocol_code = NA_integer_, duration_minutes = NA_integer_, 
effort_distance_km = NA_integer_, effort_area_ha = NA_integer_, 
number_observers = NA_integer_, all_species_reported = NA_integer_, 
group_identifier = NA_integer_, year = NA_integer_, checklist_id = NA_integer_, 
yday = NA_integer_), class = "factor", .Label = c("constant", 
"aggregate", "identity")), row.names = c("3", "3.1", "3.2"), class = "data.frame")
기능.
match_col_names <- function(x){

  col_names <- list(date = c("observation_date", "date"),
                    C =    c("observation_count", "count","routetotal"),
                    yday  = c("dayofyear"),
                    latitude  = c("lat"),
                    longitude = c("lon","long")
                    )

  for(i in seq_along(col_names)){
    newname=names(col_names)[i]
    oldnames=col_names[[i]]

  toreplace = names(x)[which(names(x) %in% oldnames)]
  x <- x %>%
    rename_with(~newname, toreplace)
}

return(x)

}

기능을 적용합니다.
x <- match_col_names(x)

실행 시간을 위해 데이터 테이블 구조를 사용할 것을 제안합니다.

> df = data.table(x = 1:10, y = 3:12, z = 4:13)
> oldnames = c("x","y","z")
> newnames = c("X","Y","Z")
> library(microbenchmark)
> library(data.table)
> library(dplyr)
> microbenchmark(dplyr_1 = df %>% rename_at(vars(oldnames), ~ newnames) ,
+                dplyr_2 = df %>% rename(X=x,Y=y,Z=z) ,
+                data_tabl1= setnames(copy(df), old = c("x","y","z") , new = c("X","Y","Z")),
+                times = 100) 
Unit: microseconds
       expr    min      lq     mean  median      uq     max neval
    dplyr_1 5760.3 6523.00 7092.538 6864.35 7210.45 17935.9   100
    dplyr_2 2536.4 2788.40 3078.609 3010.65 3282.05  4689.8   100
 data_tabl1  170.0  218.45  368.261  243.85  274.40 12351.7   100

사용하는 기본 방법setNames그것을 []첫 번째 시합을 할 것입니다.

names(x) <- setNames(c(newnames, names(x)), c(oldnames, names(x)))[names(x)]

names(x) <- (\(.) setNames(c(newnames, .), c(oldnames, .))[.])(names(x)) #Variant

x
#  A w B
#1 1 2 3

용사를 합니다.transform.

names(x) <- do.call(transform, c(list(as.list(setNames(names(x), names(x)))),
                                 as.list(setNames(newnames, oldnames))))

데이터.

x = data.frame(q=1,w=2,e=3)
oldnames = c("q","e")
newnames = c("A","B")

언급URL : https://stackoverflow.com/questions/20987295/rename-multiple-columns-by-names

반응형