Я хочу связать строки из двух разных фреймов данных, где один фрейм данных содержит столбец хеш-значений, тогда как второй фрейм данных не содержит этот столбец.
library(tidyverse)
library(openssl)
df <- data.frame(x = sha3(letters[1:3], size = 512),
y = 1:3)
df2 <- data.frame(y = 4:6)
df |>
bind_rows(df2)
При попытке связать строки я получаю следующую ошибку:
Error in `bind_rows()`:
! Can't combine `..1` <hash> and `..2` <vctrs:::common_class_fallback>.
Run `rlang::last_trace()` to see where the error occurred.
Я каким-то образом понимаю, откуда это взялось, потому что второй фрейм данных не содержит столбца x. Тем не менее, мой ожидаемый/желаемый результат заключался бы в том, что функцияbind_rows все равно будет работать и просто заполнит столбец x NA для df2.
Обновлено:
Я придумал небольшой обходной путь, просто преобразовав хэш-столбец из df обратно в символьный, но мне все еще интересно, смогу ли я вообще предотвратить ошибку.





Рекомендую использовать rbind.fill:
plyr::rbind.fill(df, df2)
Это потому, что sha3() преобразует вектор в хеш. Вы можете преобразовать его, например. с as.character(),
library(dplyr)
library(openssl)
df <- data.frame(x = as.character(sha3(letters[1:3]), size = 512),
y = 1:3)
df2 <- data.frame(y = 4:6)
df |>
bind_rows(df2)
Выход:
x y
1 80084bf2fba02475726feb2cab2d8215eab14bc6bdd8bfb2c8151257032ecd8b 1
2 b039179a8a4ce2c252aa6f2f25798251c19b75fc1508d9d511a191e0487d64a7 2
3 263ab762270d3b73d3e2cddf9acc893bb6bd41110347e5d5e4bd1d3c128ea90a 3
4 <NA> 4
5 <NA> 5
6 <NA> 6
В базе мы можем сделать
df = data.frame(x = openssl::sha3(letters[1:3], size = 512), y = 1:3)
df2 = data.frame(y = 4:6)
df2[setdiff(names(df), names(df2))]<-NA
new = rbind(df, df2)
rm(df, df2) # optional
new
#> x
#> 1 697f2d856172cb8309d6b8b97dac4de344b549d4dee61edfb4962d8698b7fa803f4f93ff24393586e28b5b957ac3d1d369420ce53332712f997bd336d09ab02a
#> 2 8446c46ee03793ba6e5813ba0db4480008926dd1d19efe2c8eb92f9034da974d2171ae483f29ce3a79ed4fdd621ae1ed14fe12532af95ddd0728779ce5aa842d
#> 3 bfe4d7f7377116dc15f794d902621797b72b32396382de2b6e49d4f1d7eabdfddcfc3bc127bb67f92f9458a5733bb21804e7ccd56b4b6f81049339f477cd279d
#> 4 <NA>
#> 5 <NA>
#> 6 <NA>
#> y
#> 1 1
#> 2 2
#> 3 3
#> 4 4
#> 5 5
#> 6 6
где new — новый объект класса data.frame.
Проблема не специфична для хэшей. Это происходит, если у вас есть объект, для которого не определен метод c.
bind_rows использует vctrs::vec_rbind и в документации сказано:
Если объединяемые столбцы наследуются от общего класса, vec_rbind() падает. вернуться к base::c(), если для этого существует метод c() иерархия классов.
Здесь это не совсем тот случай (нет общего класса), но мы видим <vctrs:::common_class_fallback> в сообщении об ошибке. Если мы определим простой c.hash, это в некоторой степени работает. К сожалению, это не сохраняет класс. Я не знаю, почему.
library(openssl)
library(dplyr)
c.hash <- function(...) {
args <- list(...)
class <- oldClass(args[[1]])
dargs <- lapply(args, unclass)
res <- do.call(c, dargs)
oldClass(res) <- class
res
}
x <- sha3(letters[1:3], size = 512)
class(c(x, NA))
#[1] "hash" "sha3-512"
df <- data.frame(x = sha3(letters[1:3], size = 512),
y = 1:3)
df2 <- data.frame(y = 4:6)
test <- df |>
bind_rows(df2)
class(test$x)
#[1] "character"