R:在两个数据帧之间更改/匹配公共列的数据类型

时间:2017-12-13 18:04:34

标签: r dataframe

说我有这个数据框:

# Original data frame
df_1 <- data.frame(a = sample(1:10, 5), 
                   b = letters[1:5], 
                   c = sample(c(TRUE, FALSE), 5, replace = TRUE),
                   d = 6:10)
#  a b     c  d
#1 7 a FALSE  6
#2 9 b  TRUE  7
#3 3 c  TRUE  8
#4 5 d  TRUE  9
#5 6 e  TRUE 10

我还有第二个数据框,其中有一些与第一个相同的列:

# Data frame with wonky data types
df_2 <- data.frame(a = as.character(sample(1:10, 5)), 
                   foo = 1:5,
                   b = letters[1:5], 
                   bar = runif(5),
                   c = as.character(sample(c(TRUE, FALSE), 5, replace = TRUE)),
                   stringsAsFactors = FALSE)

#   a foo b       bar     c
#1 10   1 a 0.1185343 FALSE
#2  5   2 b 0.3081978  TRUE
#3  6   3 c 0.4409280  TRUE
#4  8   4 d 0.5081508 FALSE
#5  7   5 e 0.7404537 FALSE

请注意df_2df_1共有的列(即abc)不一定具有相同的数据键入df_1中的相应列。例如,a中的df_1属于integer类型,而a中的df_2属于character类型。

我想要做的是将df_2中同样存在于df_1中的所有列转换为df_1列的数据类型。

我的第一个希望是我可以绑定它们并且会自动进行转换:

library(dplyr)
bind_rows(df_1, df_2)

但是,没有:

  

bind_rows_(x,.id)出错:列a无法从   整数到字符

所以,我的下一次尝试是弄清楚哪些列是共同的:

# Common columns
common <- names(df_2)[names(df_2) %in% names(df_1)]

现在,如果我想将它们全部转换为numeric,我可以使用

df_2 %>% mutate_at(common, as.numeric)

但它们都是不同的数据类型,所以我需要使用相应的数据类型。我认为不管怎样我可以使用as传递来自lapply(df_1, class)的相应类,但细节让我不知所措。我认为必须有一个简单,优雅的解决方案,而且我已经过时了,但到目前为止我还没有运气。有什么想法吗?

1 个答案:

答案 0 :(得分:2)

使用match.fun的某些内容可行:

str(df_1) ## The source classes...
# 'data.frame': 5 obs. of  4 variables:
#  $ a: int  4 2 5 9 8
#  $ b: Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5
#  $ c: logi  FALSE FALSE TRUE FALSE FALSE
#  $ d: int  6 7 8 9 10

str(df_2) ## Before conversion
# 'data.frame': 5 obs. of  5 variables:
#  $ a  : chr  "8" "10" "9" "3" ...
#  $ foo: int  1 2 3 4 5
#  $ b  : chr  "a" "b" "c" "d" ...
#  $ bar: num  0.294 0.34 0.372 0.459 0.736
#  $ c  : chr  "FALSE" "TRUE" "TRUE" "FALSE" ...

这是转换步骤:

df_2[common] <- lapply(common, function(x) {
  match.fun(paste0("as.", class(df_1[[x]])))(df_2[[x]])
})

str(df_2) ## After conversion
# 'data.frame': 5 obs. of  5 variables:
#  $ a  : int  8 10 9 3 1
#  $ foo: int  1 2 3 4 5
#  $ b  : Factor w/ 5 levels "a","b","c","d",..: 1 2 3 4 5
#  $ bar: num  0.294 0.34 0.372 0.459 0.736
#  $ c  : logi  FALSE TRUE TRUE FALSE FALSE