dplyr bind_rows mutate类型匹配

4

假设我有两个简单的数据框,如下:

stuff <- data.frame('a', 'b')
col1 <- c(1,2,3)
stuff <- data.frame(col1)
col1 <- c('1','2', '3')
stuff2 <- data.frame(col1)

我希望将它们合并成一个数据框,并尝试使用dplyrbind_rows,例如:

bind_rows(stuff, stuff2)

但是(并不出乎意料地),我遇到了问题:

绑定行时出现错误:col1列无法从数字转换为因子

我能否告诉 bind_rows 将行变异为目标(或尝试这样做)?


存在一种类型问题。你需要像这样的内容 list(stuff, stuff2) %>% map_df( ~ .x %>% mutate(col1 = as.numeric(as.character(col1)))) 吗? - akrun
@akrun 是的,除了我不想拼出所有的列,因为我有数百个;而且在某些列中,不匹配是单向的,在其他列中不匹配是另一种情况...所以我希望类型可以自动计算。 - zaitsman
2
我猜你需要 stuff %>% mutate_all(funs(type.convert(as.character(.), as.is = TRUE))),即如果我们有一个数据框列表,则使用上面的 map,例如 list(stuff, stuff2) %>% map_df( ~ .x %>% mutate_all(funs(type.convert(as.character(.), as.is = TRUE)))) - akrun
@akrun 但是如果我的列是混合的呢?有些是字符,有些是数字等。 - zaitsman
1
然后它变得困难,因为这是一个需要您手动提供的决定。 - akrun
3个回答

1
你可以尝试使用rbind(...),只有当两个data.frame具有相同的列数和列名时才能使用。
rbind(stuff, stuff2, stringsAsFactors = FALSE)

#   col1
# 1    1
# 2    2
# 3    3
# 4    1
# 5    2
# 6    3

选项#2:如果列名不相同

可以尝试使用c(...)的自动强制转换功能。该函数的文档建议如下:

All arguments are coerced to a common type which is the type of the returned value,
and all attributes except names are removed
现在,如果所有的data.frames都有相同数量的列并且顺序相同,则可以尝试以下操作:
library(purrr)

map2_df(stuff, stuff2, c)

# # A tibble: 6 x 1
#    col1
#   <dbl>
# 1  1.00
# 2  2.00
# 3  3.00
# 4  1.00
# 5  2.00
# 6  3.00

注意: 在应用上述代码之前,请确保所有的factor类型列已经转换为character类型,以避免出现意外结果。
数据:
col1 <- c(1,2,3)
stuff <- data.frame(col1)
col1 <- c('1','2', '3')
stuff2 <- data.frame(col1)

1
我会使用data.table的rbindlist函数... 由于此功能需要列表作为输入,因此您将自动失去字符因子问题... rbindlist还具有一些使生活更轻松的功能(而且它也非常快!)
#lets make'a named list
l <- list( stuff = stuff, stuff2 = stuff2 ) 
#now bind the two df's together
library(data.table)
rbindlist( l, use.names = TRUE )
#    col1
# 1:    1
# 2:    2
# 3:    3
# 4:    1
# 5:    2
# 6:    3

当您需要更多功能时,更好的东西就会出现...比如说您想知道哪些数据来自哪个df...这时候就要用到名称列表。

rbindlist( l, use.names = TRUE, idcol = TRUE )
#      .id col1
#1:  stuff    1
#2:  stuff    2
#3:  stuff    3
#4: stuff2    1
#5: stuff2    2
#6: stuff2    3

或者,当不是所有的列名都在所有的数据框中出现时:

col2 <- c('1','2', '3')
stuff2 <- data.frame(col2)
rbindlist( l, use.names = TRUE, fill = TRUE, idcol = "origin" )
#    origin col1 col2
# 1:  stuff    1 <NA>
# 2:  stuff    2 <NA>
# 3:  stuff    3 <NA>
# 4: stuff2   NA    1
# 5: stuff2   NA    2
# 6: stuff2   NA    3

如果列名不同,但仍希望将两个数据框合并到一列中:
col1 <- c(1,2,3)
stuff <- data.frame(col1)
col2 <- c('1','2', '3')
stuff2 <- data.frame(col2)
#create a named list
l <- list(stuff = stuff, stuff2 = stuff2) 
rbindlist( l )

#    col1
# 1:    1
# 2:    2
# 3:    3
# 4:    1
# 5:    2
# 6:    3

0
如果您有混合数据类型,请尝试以下方法:
#data
stuff <- data.frame('a', 'b')
col1 <- c(1,2,3)
stuff <- data.frame(col1)
col1 <- c('1','2', '3')
stuff2 <- data.frame(col1)
#for loop to convert classes from one df to the other
for (x in colnames(stuff)) {
  stuff[,x] <- eval(call( paste0("as.", class(stuff2[,x])), stuff[,x]) )}
#bind_rows
bind_rows(stuff,stuff2)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接