Я всегда находил, что ActiveRecord хорош для быстрых основанных на CRUD приложений, где Модель является относительно плоской (как в, не много иерархий классов). Однако для приложений со сложными иерархиями OO, DataMapper является, вероятно, лучшим решением. В то время как ActiveRecord принимает 1:1 отношение между Вашими таблицами и Вашими объектами данных, такие отношения становятся громоздкими с более сложными доменами. В его книга по шаблонам , Martin Fowler указывает, что ActiveRecord склонен ломаться при условиях, где Ваша Модель довольно сложна, и предлагает DataMapper как альтернатива.
я нашел, что это верно на практике. В случаях, где у Вас есть большое наследование в Вашем домене, более трудно отобразить наследование на Ваш RDBMS, чем это должно отобразить ассоциации или состав.
способ, которым я делаю это, состоит в том, чтобы иметь "доменные" объекты, к которым получают доступ Ваши контроллеры через эти DataMapper (или "уровень служб") классы. Они непосредственно не зеркально отражают базу данных, но действуют как Ваше представление OO для некоторого реального объекта. Скажите, что Вы имеете Пользовательский класс в своем домене и должны иметь ссылки на, или наборы других объектов, уже загруженных при получении того Пользовательского объекта. Данные могут прибывать из многих различных таблиц, и шаблон ActiveRecord может сделать их действительно трудно.
Вместо того, чтобы загрузить Пользовательский объект непосредственно и получить доступ к данным с помощью API стиля ActiveRecord, код контроллера получает Пользовательский объект путем называния API UserMapper.getUser () методом, например. Именно тот картопостроитель ответственен за загрузку любых связанных объектов от их соответствующих таблиц и возврата завершенного Пользовательского объекта "домена" вызывающей стороне.
По существу, Вы просто добавляете другой слой абстракции для создания кода более managable. Содержат ли Ваши классы DataMapper необработанный пользовательский SQL, или звонит в API уровня абстракции данных, или даже получите доступ к шаблону ActiveRecord сами, действительно не имейте значения для кода контроллера, который получает хороший, заполненный Пользовательский объект.
Так или иначе, это - то, как я делаю это.
Это могло быть вызвано несовпадением типов в двух data.frames
.
В первую очередь проверочные типы (классы). Для диагностических целей сделайте следующее:
new2old <- rbind( alltime, all2008 ) # this gives you a warning
old2new <- rbind( all2008, alltime ) # this should be without warning
cbind(
alltime = sapply( alltime, class),
all2008 = sapply( all2008, class),
new2old = sapply( new2old, class),
old2new = sapply( old2new, class)
)
Я ожидаю, что будет строка, похожая на:
alltime all2008 new2old old2new
... ... ... ... ...
some_column "factor" "numeric" "factor" "character"
... ... ... ... ...
Если да, то объяснение:
rbind
не проверять соответствие типов. Если вы проанализируете код rbind.data.frame
, то увидите, что первый аргумент инициализирует типы вывода. Если в первом типе data.frame указан фактор, то выходной столбец data.frame является фактором с уровнями уникальными (c (уровни (x1), уровни (x2)))
. Но когда во втором столбце data.frame не фактор, тогда уровни (x2)
равно NULL
, поэтому уровни не расширяются.
Это означает, что ваши выходные данные неверны! Есть NA
вместо истинных значений
Я полагаю, что:
Решение:
найти неправильный столбец и найти причину, по которой он неправильный, и исправить. Устраняйте причину, а не симптомы.
Как было предложено в предыдущем ответе, считайте столбцы как символы и выполните преобразование в коэффициенты после rbind
.
SQLFetch
(я полагаю, RODBC ) также имеет аргумент stringsAsFactors
или as.is
для управления преобразованием символов.
Допустимые значения такие же, как для read.table
, например, as.is = TRUE
или некоторый номер столбца.
«Простой» способ - просто не устанавливать ваши строки в качестве факторов при импорте текстовых данных.
Примечание что функции читают. {table, csv, ...}
принимают параметр stringsAsFactors
, который по умолчанию имеет значение TRUE
. Вы можете установить это значение на FALSE
во время импорта и rbind
-ing ваших данных.
Если вы хотите, чтобы столбец был фактором в конце, вы тоже можете это сделать.
Например:
alltime <- read.table("alltime.txt", stringsAsFactors=FALSE)
all2008 <- read.table("all2008.txt", stringsAsFactors=FALSE)
alltime <- rbind(alltime, all2008)
# If you want the doctor column to be a factor, make it so:
alltime$doctor <- as.factor(alltime$doctor)