การเขียนฟังก์ชันที่กำหนดเองเพื่อแปลงคลาสของตัวแปรในดาต้าเฟรมโดยยึดตามตารางอื่น
ฉันกำลังพยายามเขียนฟังก์ชันที่สามารถรับ:
- data frame (
df_1
) ซึ่งต้องมีการแปลงคลาสของคอลัมน์ - data frame อื่น (
df_2
) ที่มีแถวสำหรับแต่ละตัวแปรของdf_1
- คอลัมน์
df_2
ที่ระบุคลาสแต่ละตัวแปรในdf_1
ควรถูกแปลงเป็น
ตัวอย่าง
1 - เฟรมข้อมูล ( df_1
) ที่มีข้อมูลของฉัน (และคลาสของตัวแปรที่จะแปลง)
library(tibble)
library(dplyr)
set.seed(2021)
df_1 <-
tibble(name = c("john", "jack", "mary", "matt", "elizabeth", "richard", "carlos", "george", "ferdinand", "william"),
height = sample(155:200, size = 10),
weight = sample(50:100, size = 10),
age = sample(20:100, size = 10),
gender = sample(c("male", "female"), size = 10, replace = TRUE),
preferred_pet = sample(c("dog", "cat", "frog", "rabbit"), size= 10, replace = TRUE)) %>%
mutate(across(everything(), as.character))
## # A tibble: 10 x 6
## name height weight age gender preferred_pet
## <chr> <chr> <chr> <chr> <chr> <chr>
## 1 john 161 100 38 female frog
## 2 jack 192 67 87 female dog
## 3 mary 193 52 24 male rabbit
## 4 matt 166 95 92 male dog
## 5 elizabeth 160 89 82 female cat
## 6 richard 199 75 57 male dog
## 7 carlos 195 85 37 female rabbit
## 8 george 159 86 62 male rabbit
## 9 ferdinand 177 71 78 female cat
## 10 william 197 80 89 female rabbit
2 - กรอบข้อมูล ( df_2
) พร้อมคลาสที่จะแปลงdf_1
คอลัมน์เป็น
set.seed(2021)
df_2 <-
tibble(var_name = c("name", "height", "weight", "gender", "preferred_pet", "record_creation"),
var_class = c("character", "numeric", "numeric", "factor", "factor", "datetime")) %>%
slice(sample(1:n()))
## # A tibble: 6 x 2
## var_name var_class
## <chr> <chr>
## 1 weight numeric
## 2 record_creation datetime
## 3 height numeric
## 4 name character
## 5 gender factor
## 6 preferred_pet factor
3 - การสร้างฟังก์ชันสำหรับการแปลงคลาส
ฉันเคยเห็นวิธีแก้ปัญหาของ @ akrun ที่นี่ซึ่งดูเหมือนจะใกล้เคียงกับสิ่งที่ฉันพยายามจะบรรลุ
library(purrr)
library(stringr)
my_df <- iris
my_types <- c("factor", "character", "double", "logical", "character")
my_df[] <- map2(my_df, str_c("as.", my_types), ~ get(.y)(.x))
อย่างไรก็ตามการแก้ปัญหานี้ไม่ได้อยู่ในสถานการณ์เช่นเหมืองที่ชื่อตัวแปรของdf_1
ไม่จำเป็นต้องปรากฏในdf_2
และในทำนองเดียวกันรวมถึงตัวแปรที่ไม่จำเป็นต้องปรากฏในdf_2$var_name
df_1
ผมจะดีใจสำหรับความคิดใด ๆ ในการสร้างฟังก์ชั่นสำหรับการแปลงdf_1
's vars df_2
เรียนตามข้อมูลที่พบใน การหาวิธีแก้ปัญหาโดยใช้tidyverse
ฟังก์ชันจะเหมาะอย่างยิ่ง ขอบคุณ!
คำตอบ
นี่คือแนวทางในการใช้ประโยชน์across
และcur_column
:
library(dplyr) #version >= 1.0.0
df_1 %>%
mutate(across(any_of(df_2$var_name), ~get(paste0("as.",df_2[df_2$var_name == cur_column(),"var_class"]))(.x)))
# A tibble: 10 x 6
name height weight age gender preferred_pet
<chr> <dbl> <dbl> <chr> <fct> <fct>
1 john 161 100 38 female frog
2 jack 192 67 87 female dog
3 mary 193 52 24 male rabbit
4 matt 166 95 92 male dog
5 elizabeth 160 89 82 female cat
6 richard 199 75 57 male dog
7 carlos 195 85 37 female rabbit
8 george 159 86 62 male rabbit
9 ferdinand 177 71 78 female cat
10 william 197 80 89 female rabbit
มั่นใจผู้ช่วยเลือกว่าคุณจะพยายามที่จะคอลัมน์กลายพันธุ์ที่มีอยู่ในปัจจุบันany_of
df_2
อาร์กิวเมนต์ที่สองคือฟังก์ชันที่ใช้กับคอลัมน์ที่มีอยู่ คุณสามารถใช้cur_column()
เพื่อเข้าถึงชื่อของคอลัมน์ที่กำลังกลายพันธุ์ จากนั้นเราก็ค้นหาชื่อคอลัมน์นั้นdf_2
และส่งคืนค่าที่var_class
คุณต้องการ จากนั้นใช้get()
จากฐาน R (.x)
เพื่อกลับมาฟังก์ชั่นที่เหมาะสมและใช้ที่คอลัมน์ที่มี
หากคุณต้องการกำหนดฟังก์ชั่นและส่งชื่อคอลัมน์โดยไม่ต้องใส่เครื่องหมายเหมือนที่คุณทำกับฟังก์ชัน tidyverse อื่น ๆ คุณสามารถใช้rlang::enquo
:
library(rlang)
change_class_by_table <- function(data,data_ref,column_name,column_class){
data %>%
mutate(across(any_of(pull(data_ref,!!enquo(column_name))),
~get(paste0("as.",filter(data_ref, !!enquo(column_name) == cur_column()) %>%
pull(!!enquo(column_class))))(.x)))
}
change_class_by_table(df_1,df_2,var_name,var_class)
## A tibble: 10 x 6
# name height weight age gender preferred_pet
# <chr> <dbl> <dbl> <chr> <fct> <fct>
# 1 john 161 100 38 female frog
# 2 jack 192 67 87 female dog
# 3 mary 193 52 24 male rabbit
# ...