У меня есть множество фреймов данных со многими столбцами, где имя столбца заканчивается на «ID». Какой самый простой способ изменить тип каждого столбца, заканчивающегося на «ID». В идеале я бы передал импортированный фрейм данных функции, которая вернула бы тот же фрейм данных, но с измененными типами столбцов. Я определенно не могу жестко закодировать имена столбцов, поскольку я не буду знать заранее, что это за столбцы.

Вот несколько примеров данных:

test_data <- structure(list(ContactID = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
), SystemID = c(3, 1, 5, 4, 3, 5, 35, 1, 55, 52, 9), Value1 = c("A", 
"B", "C", "D", "E", "F", "E", "G", "D", "S", "C"), Value2 = c("1/01/2020", 
"2/01/2020", "3/01/2020", "4/01/2020", "5/01/2020", "6/01/2020", 
"7/01/2020", "8/01/2020", "9/01/2020", "10/01/2020", "11/01/2020"
), OtherID = c(10004, 10009, 10002, 10007, 10099, 10010, 10002, 
10004, 10002, 10007, 10099)), class = c("spec_tbl_df", "tbl_df", 
"tbl", "data.frame"), row.names = c(NA, -11L), spec = structure(list(
    cols = list(ContactID = structure(list(), class = c("collector_double", 
    "collector")), SystemID = structure(list(), class = c("collector_double", 
    "collector")), Value1 = structure(list(), class = c("collector_character", 
    "collector")), Value2 = structure(list(), class = c("collector_character", 
    "collector")), OtherID = structure(list(), class = c("collector_double", 
    "collector"))), default = structure(list(), class = c("collector_guess", 
    "collector")), skip = 1), class = "col_spec"))

Столбцы ContactID, SystemID и OtherID были импортированы из файла CSV (с использованием read_csv из readr) и поэтому обозначены как числовые. Мне нужна функция, в которой я могу передать этот (или любой другой фрейм данных), чтобы изменить любые столбцы, заканчивающиеся идентификатором, на символ.

Я пробовал это, но это кажется очень неуклюжим. Ищу более изящное решение.

  change_ID_cols <- function(x) {
    
    id_cols <- grep("ID$", colnames(x))
    
    for (i in id_cols) {
      for (j in 1:nrow(x)) {
        x[j,i] <- as.character(x[j,i])
      }
    }
    x
  }
r
0
Mist 8 Ноя 2020 в 10:54

3 ответа

Лучший ответ

Это работает:

library(dplyr)
test_data %>% mutate(across(ends_with('ID'), as.character))
# A tibble: 11 x 5
   ContactID SystemID Value1 Value2     OtherID
   <chr>     <chr>    <chr>  <chr>      <chr>  
 1 1         3        A      1/01/2020  10004  
 2 2         1        B      2/01/2020  10009  
 3 3         5        C      3/01/2020  10002  
 4 4         4        D      4/01/2020  10007  
 5 5         3        E      5/01/2020  10099  
 6 6         5        F      6/01/2020  10010  
 7 7         35       E      7/01/2020  10002  
 8 8         1        G      8/01/2020  10004  
 9 9         55       D      9/01/2020  10002  
10 10        52       S      10/01/2020 10007  
11 11        9        C      11/01/2020 10099  
> 
3
Karthik S 8 Ноя 2020 в 07:56

Вам не нужно менять каждое значение индивидуально на символ. Вы можете сразу превратить весь столбец в символ. Чтобы сделать это для нескольких столбцов, используйте lapply.

change_ID_cols <- function(x) {
  id_cols <- grep("ID$", colnames(x))
  x[id_cols] <- lapply(x[id_cols], as.character)
  x
}
1
Ronak Shah 8 Ноя 2020 в 07:59

Опция с data.table будет

library(data.table)
nm <- grep('ID$', names(test_data), value = TRUE)
setDT(test_data)[, (nm) := lapply(.SD, as.character), .SDcols = nm]
0
akrun 8 Ноя 2020 в 22:05