R 中关于分组数据、数据转换和 mlogit 设置的多项式 logit 模型
Multinomial logit model in R on grouped data, data conversion and mlogit set-up
我想估计 R 中多项式 logit 模型的参数,想知道如何正确构建我的数据。我正在使用“mlogit”包。
目的是模拟人们对交通方式的选择。但是,数据集是聚合级别的时间序列,例如:
必须将此数据从分组计数数据重塑为未分组数据。我的方法是为每个人创建三个新行,所以我最终得到一个如下所示的数据集:
对于分组数据中每个人的选择,我创建了三个新行并使用 chid 将这三个行联系起来
排在一起。我现在想要 运行 :
mlogit.data(MyData, choice = “choice”, chid.var = “chid”, alt.var = “mode”).
这是正确的做法吗?还是我误解了 chid 函数的用途?
您尝试将价格和时间作为真实变量作为模型的一部分吗?
如果不是,则您不需要 "unaggregate" 该数据。直接处理结果计数(即使使用协变量)也很好。我不知道在 mlogit 中执行此操作的细节,但使用 multinom,这很简单,而且我想使用 mlogit 是可能的:
# Assuming your original data frame is saved in "df" below
library(nnet)
response <- as.matrix(df[,c('Car', 'Bus', 'Bicycle')])
predictor <- df$Month
# Determine how the multinomial distribution parameter estimates
# are changing as a function of time
fit <- multinom(response ~ predictor)
在上述情况下,结果计数直接与一个协变量 "Month" 一起使用。如果您不关心协变量,您也可以只使用 multinom(response ~ 1)
但很难说出您真正想要做什么。
查看 mlogit 包中的 "TravelMode" 数据和一些示例,我相信如果您真的想要每个人的个人记录,您选择的选项是正确的。
很遗憾,这是从 stats.stackexchange.com 迁移而来的,因为您可能会在那里得到更好的答案。
mlogit
包需要个人数据,并且可以接受 "wide" 或 "long" 数据。在前者中,每个人都有一行表示所选择的模式,模式特定变量(示例中的时间和价格)的每个组合都有单独的列。在长格式中,每个人都有 n 行,其中 n 是模式数,第二列包含 TRUE
或 FALSE
表示为每个人选择了哪种模式,还有一列用于每个特定于模式的变量。在内部,mlogit
使用长格式数据集,但您可以提供宽格式并让 mlogit
为您转换它。在这种情况下,只有两个变量,这可能是更好的选择。
由于 mlogit
需要个人,而您有个人数量,处理此问题的一种方法是扩展您的数据,使每种模式具有适当的行数,填写结果 data.frame 与变量组合。下面的代码就是这样做的:
df.agg <- data.frame(month=1:4,car=c(3465,3674,3543,4334),bus=c(1543,2561,2432,1266),bicycle=c(453,234,123,524))
df.lvl <- data.frame(mode=c("car","bus","bicycle"), price=c(120,60,0), time=c(5,10,30))
get.mnth <- function(mnth) data.frame(mode=rep(names(df.agg[2:4]),df.agg[mnth,2:4]),month=mnth)
df <- do.call(rbind,lapply(df.agg$month,get.mnth))
cols <- unlist(lapply(df.lvl$mode,function(x)paste(names(df.lvl)[2:3],x,sep=".")))
cols <- with(df.lvl,setNames(as.vector(apply(df.lvl[2:3],1,c)),cols))
df <- data.frame(df, as.list(cols))
head(df)
# mode month price.car time.car price.bus time.bus price.bicycle time.bicycle
# 1 car 1 120 5 60 10 0 30
# 2 car 1 120 5 60 10 0 30
# 3 car 1 120 5 60 10 0 30
# 4 car 1 120 5 60 10 0 30
# 5 car 1 120 5 60 10 0 30
# 6 car 1 120 5 60 10 0 30
现在我们可以使用mlogit(...)
library(mlogit)
fit <- mlogit(mode ~ price+time|0 , df, shape = "wide", varying = 3:8)
summary(fit)
#...
# Frequencies of alternatives:
# bicycle bus car
# 0.055234 0.323037 0.621729
#
# Coefficients :
# Estimate Std. Error t-value Pr(>|t|)
# price 0.0047375 0.0003936 12.036 < 2.2e-16 ***
# time -0.0740975 0.0024303 -30.489 < 2.2e-16 ***
# ...
coef(fit)["time"]/coef(fit)["price"]
# time
# -15.64069
所以这表明减少 1(分钟?)的旅行时间大约值 15(美元)?
此分析忽略了 month
变量。我不清楚你将如何合并它,因为月份既不是模式特定的也不是个人特定的。您可以 "pretend" 那个月是特定于个人的,并使用像这样的模型公式:mode ~ price+time|month
,但是对于您的数据集,系统在计算上是单一的。
要重现其他答案的结果,您可以使用 mode ~ 1|month
和 reflevel="car"
。这忽略了特定于模式的变量,只估计了月份的影响(相对于 mode = car)。
mlogit
here.
上有一个很好的教程
我想估计 R 中多项式 logit 模型的参数,想知道如何正确构建我的数据。我正在使用“mlogit”包。
目的是模拟人们对交通方式的选择。但是,数据集是聚合级别的时间序列,例如:
必须将此数据从分组计数数据重塑为未分组数据。我的方法是为每个人创建三个新行,所以我最终得到一个如下所示的数据集:
对于分组数据中每个人的选择,我创建了三个新行并使用 chid 将这三个行联系起来 排在一起。我现在想要 运行 : mlogit.data(MyData, choice = “choice”, chid.var = “chid”, alt.var = “mode”).
这是正确的做法吗?还是我误解了 chid 函数的用途?
您尝试将价格和时间作为真实变量作为模型的一部分吗?
如果不是,则您不需要 "unaggregate" 该数据。直接处理结果计数(即使使用协变量)也很好。我不知道在 mlogit 中执行此操作的细节,但使用 multinom,这很简单,而且我想使用 mlogit 是可能的:
# Assuming your original data frame is saved in "df" below
library(nnet)
response <- as.matrix(df[,c('Car', 'Bus', 'Bicycle')])
predictor <- df$Month
# Determine how the multinomial distribution parameter estimates
# are changing as a function of time
fit <- multinom(response ~ predictor)
在上述情况下,结果计数直接与一个协变量 "Month" 一起使用。如果您不关心协变量,您也可以只使用 multinom(response ~ 1)
但很难说出您真正想要做什么。
查看 mlogit 包中的 "TravelMode" 数据和一些示例,我相信如果您真的想要每个人的个人记录,您选择的选项是正确的。
很遗憾,这是从 stats.stackexchange.com 迁移而来的,因为您可能会在那里得到更好的答案。
mlogit
包需要个人数据,并且可以接受 "wide" 或 "long" 数据。在前者中,每个人都有一行表示所选择的模式,模式特定变量(示例中的时间和价格)的每个组合都有单独的列。在长格式中,每个人都有 n 行,其中 n 是模式数,第二列包含 TRUE
或 FALSE
表示为每个人选择了哪种模式,还有一列用于每个特定于模式的变量。在内部,mlogit
使用长格式数据集,但您可以提供宽格式并让 mlogit
为您转换它。在这种情况下,只有两个变量,这可能是更好的选择。
由于 mlogit
需要个人,而您有个人数量,处理此问题的一种方法是扩展您的数据,使每种模式具有适当的行数,填写结果 data.frame 与变量组合。下面的代码就是这样做的:
df.agg <- data.frame(month=1:4,car=c(3465,3674,3543,4334),bus=c(1543,2561,2432,1266),bicycle=c(453,234,123,524))
df.lvl <- data.frame(mode=c("car","bus","bicycle"), price=c(120,60,0), time=c(5,10,30))
get.mnth <- function(mnth) data.frame(mode=rep(names(df.agg[2:4]),df.agg[mnth,2:4]),month=mnth)
df <- do.call(rbind,lapply(df.agg$month,get.mnth))
cols <- unlist(lapply(df.lvl$mode,function(x)paste(names(df.lvl)[2:3],x,sep=".")))
cols <- with(df.lvl,setNames(as.vector(apply(df.lvl[2:3],1,c)),cols))
df <- data.frame(df, as.list(cols))
head(df)
# mode month price.car time.car price.bus time.bus price.bicycle time.bicycle
# 1 car 1 120 5 60 10 0 30
# 2 car 1 120 5 60 10 0 30
# 3 car 1 120 5 60 10 0 30
# 4 car 1 120 5 60 10 0 30
# 5 car 1 120 5 60 10 0 30
# 6 car 1 120 5 60 10 0 30
现在我们可以使用mlogit(...)
library(mlogit)
fit <- mlogit(mode ~ price+time|0 , df, shape = "wide", varying = 3:8)
summary(fit)
#...
# Frequencies of alternatives:
# bicycle bus car
# 0.055234 0.323037 0.621729
#
# Coefficients :
# Estimate Std. Error t-value Pr(>|t|)
# price 0.0047375 0.0003936 12.036 < 2.2e-16 ***
# time -0.0740975 0.0024303 -30.489 < 2.2e-16 ***
# ...
coef(fit)["time"]/coef(fit)["price"]
# time
# -15.64069
所以这表明减少 1(分钟?)的旅行时间大约值 15(美元)?
此分析忽略了 month
变量。我不清楚你将如何合并它,因为月份既不是模式特定的也不是个人特定的。您可以 "pretend" 那个月是特定于个人的,并使用像这样的模型公式:mode ~ price+time|month
,但是对于您的数据集,系统在计算上是单一的。
要重现其他答案的结果,您可以使用 mode ~ 1|month
和 reflevel="car"
。这忽略了特定于模式的变量,只估计了月份的影响(相对于 mode = car)。
mlogit
here.