我有一个数据框,其中包含有关城市人口密度的数据,该数据取决于与市中心的距离(“空间距离剖面”)。
数据框如下所示(示例):
console.log([2,3].includes(1));
“城市”包含城市名称或标识符,而变量“ km1-km4”包含该距离内的人口密度的对数。请注意,示例中的观察值3没有km4的数据;所有城市都没有km5的数据。
我要实现的目标是推断当人口密度遵循指数函数时,城市分布了多少公里。
为此,我想首先对表格的每一行运行线性回归y〜x,其中y是变量km1-kmX,x是距市中心的相应距离(1,2,3,.. )。
set.seed(1)
data <- data.frame(cities = c("city1","city2","city3"),
km1 = runif(3,6,7),
km2 = runif(3,5,6),
km3 = runif(3,4,5),
km4 = c(3.5,3.2,NA),
km5 = c(NA,NA,NA)
)
(示例中未定义可变的“距离”,因为我不知道如何将其合并到数据框中。但我希望这个想法能够实现)
因此,对于city1和city2,应使用km1-km4,而对于city3,显然仅应使用km1-km3。
然后将所得系数beta_0和beta_1作为变量存储在相应的行中。
接下来,我要使用系数来计算缺失变量的总体密度的对数,
lm(km1-kmX ~ distance)
我知道描述有些模糊;我想尽可能地扩大构思的所有细节。感谢任何帮助。
虽然可能不是必需的,但这是我在以下平台上使用R的平台:
R版本3.4.2(2017-09-28)
平台:x86_64-w64-mingw32 / x64(64位)
在以下环境下运行:Windows> = 8 x64(内部版本9200)
答案 0 :(得分:1)
假定目标是使用同一行上的非NA值与标题中的数字的线性回归来填充NA值,则首先提取构成{{1}的列名中的数值}。然后定义一个函数,该函数针对x回归行值,并据此预测NA。最后将其应用于每一行。
x
给予:
x <- as.numeric(gsub("\\D", "", names(data)[-1])) # c(1, 2, 3, 4, 5)
na.lm <- function(r, x) ifelse(is.na(r), predict(lm(r ~ x), list(x = x)), r)
cbind(data[1], t(apply(data[-1], 1, na.lm, x = x)))
答案 1 :(得分:1)
首先,我认为我们需要将您的数据从“宽”格式调整为“高”格式。这将满足Ryan的评论,即您不能对单行进行线性回归-他在技术上是正确的,但我认为他错过了您实际上每行有4-5个观测值,而不是1的要点。(注释已删除。 )
(第二:从不命名变量data
。如果您忘记在新的R会话中创建变量,则依赖于该变量的所有函数都将以奇怪且通常不直观的方式失败,而不是预期的更简单的错误消息Error: object 'data' not found
。我将在您的创建代码中使用dat
。)
使用tidyverse
中的一些软件包对此进行了演示:
library(dplyr)
library(tidyr)
library(purrr)
重塑:首先,您枚举为km1
,km2
等,但是它们是分类变量,而不是数字,我推断您希望将数字存储在其中。因此,您真正拥有的列名称(km1
)应该是数据(km = 1
)。 (哦,我删除了NA
,因为它们无助于提供模型。我们稍后再将它们带回来。)
datlong <- dat %>%
gather(km, dens, -cities) %>%
mutate(km = as.numeric(gsub("km", "", km))) %>%
rename(city = cities) %>%
filter(complete.cases(.))
datlong
# city km dens
# 1 city1 1 6.265509
# 2 city2 1 6.372124
# 3 city3 1 6.572853
# 4 city1 2 5.908208
# 5 city2 2 5.201682
# 6 city3 2 5.898390
# 7 city1 3 4.944675
# 8 city2 3 4.660798
# 9 city3 3 4.629114
# 10 city1 4 3.500000
# 11 city2 4 3.200000
现在的问题是如何对每个城市进行回归。首先,通过将城市的所有数据放在框架的一个“单元”中,让我们“整理”些东西。
datnested <- datlong %>%
group_by(city) %>%
nest(.key = "citydat")
datnested
# # A tibble: 3 x 2
# city citydat
# <fct> <list>
# 1 city1 <tibble [4 x 2]>
# 2 city2 <tibble [4 x 2]>
# 3 city3 <tibble [3 x 2]>
现在我们可以对每个数据集进行回归:
datmodel <- datnested %>%
mutate(model = map(citydat, ~ lm(dens ~ km, data = .x)))
datmodel
# # A tibble: 3 x 3
# city citydat model
# <fct> <list> <list>
# 1 city1 <tibble [4 x 2]> <S3: lm>
# 2 city2 <tibble [4 x 2]> <S3: lm>
# 3 city3 <tibble [3 x 2]> <S3: lm>
是否注意到框架中的嵌入式模型?每个看起来像这样:
datmodel$model[[1]]
# Call:
# lm(formula = dens ~ km, data = .x)
# Coefficients:
# (Intercept) km
# 7.470 -0.926
现在 that 可以在其他地方使用。让我们进行预测:
predkm <- 1:5
datpred <- datmodel %>%
mutate(pred = map(model, ~ data_frame(km = predkm, preddens = predict(.x, newdata = data.frame(km=predkm)))))
datpred
# # A tibble: 3 x 4
# city citydat model pred
# <fct> <list> <list> <list>
# 1 city1 <tibble [4 x 2]> <S3: lm> <tibble [5 x 2]>
# 2 city2 <tibble [4 x 2]> <S3: lm> <tibble [5 x 2]>
# 3 city3 <tibble [3 x 2]> <S3: lm> <tibble [5 x 2]>
类似地:
datpred$pred[[1]]
# # A tibble: 5 x 2
# km preddens
# <int> <dbl>
# 1 1 6.54
# 2 2 5.62
# 3 3 4.69
# 4 4 3.77
# 5 5 2.84
好的,那么我们如何得到一个单一的帧?
datpredonly <- datpred %>%
select(city, pred) %>%
unnest()
datpredonly
# # A tibble: 15 x 3
# city km preddens
# <fct> <int> <dbl>
# 1 city1 1 6.54
# 2 city1 2 5.62
# 3 city1 3 4.69
# 4 city1 4 3.77
# 5 city1 5 2.84
# 6 city2 1 6.37
# 7 city2 2 5.36
# 8 city2 3 4.36
# 9 city2 4 3.35
# 10 city2 5 2.34
# 11 city3 1 6.67
# 12 city3 2 5.70
# 13 city3 3 4.73
# 14 city3 4 3.76
# 15 city3 5 2.78
如果您想与原始版本进行比较(例如错误等),请尝试:
full_join(datlong, datpredonly, by = c("city", "km")) %>%
arrange(city, km)
# city km dens preddens
# 1 city1 1 6.265509 6.543607
# 2 city1 2 5.908208 5.617601
# 3 city1 3 4.944675 4.691595
# 4 city1 4 3.500000 3.765589
# 5 city1 5 NA 2.839583
# 6 city2 1 6.372124 6.367239
# 7 city2 2 5.201682 5.361514
# 8 city2 3 4.660798 4.355788
# 9 city2 4 3.200000 3.350063
# 10 city2 5 NA 2.344337
# 11 city3 1 6.572853 6.671989
# 12 city3 2 5.898390 5.700119
# 13 city3 3 4.629114 4.728249
# 14 city3 4 NA 3.756380
# 15 city3 5 NA 2.784510
因此,您讨论了使用指数回归的方法:在运行的早期对lm
的一次调用中对此进行了处理。随时可以从dens ~ km
更改为特定的指数公式。
我已将所有内容分解为几个部分。这是长链。
predkm <- 1:5
datnestedmodels <- datlong %>%
group_by(city) %>%
nest(.key = "citydat") %>%
mutate(
model = map(citydat, ~ lm(dens ~ km, data = .x)),
pred = map(model, ~ data_frame(km = predkm,
preddens = predict(.x, newdata = data.frame(km=predkm))))
)
datnestedmodels %>%
select(city, pred) %>%
unnest()
如果您喜欢(或需要)“宽”格式:
datnestedmodels %>%
select(city, pred) %>%
unnest() %>%
spread(km, preddens, sep = "")
# # A tibble: 3 x 6
# city km1 km2 km3 km4 km5
# <fct> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 city1 6.54 5.62 4.69 3.77 2.84
# 2 city2 6.37 5.36 4.36 3.35 2.34
# 3 city3 6.67 5.70 4.73 3.76 2.78