如何计算不同列中每一行的斜率和截距
How to calculate slope and intercept for every row in different columns
我正在尝试计算数据框中不同列中每一行的斜率和截距。输出(截距和斜率)应作为新列添加到原始数据框中。
为了尽可能清楚地说明我要实现的目标,我在下面提供了一些数据:
locations<-c("a","b","c")
proportion.I<-c(0.073846154, 0.079710145, 0.063218391)
proportion.II<-c(0.049773659, 0.033756955, 0.011237956)
proportion.III<-c(0.090322581, 0.100917431, 0.08051443)
abundance.I<-c(331,331,331)
abundance.II<-c(178,178,178)
abundance.III<-c(87,87,87)
output.slope<-c(5.539e-05, -4.665e-05, -2.819e-05)
output.intercept<-c(5.128e-02, 8.073e-02, 5.726e-02)
df<-data.frame(locations, proportion.I, proportion.II, proportion.III, abundance.I, abundance.II, abundance.III, output.slope, output.intercept)
*我的线性回归的 'dependent' 变量将是 'Proportion'(行 2:4),预测变量(或自变量)将是 'abundance'(行 5:7).
好吧,您的数据不是“整齐”的格式,这使得使用大多数内置函数变得困难。您可以使用 dplyr
和 tidyr
将您的数据转换为一个共享,以便更轻松地进行分组回归。例如
library(dplyr)
library(tidyr)
df %>%
select(-starts_with("output")) %>% #drop "answers"
pivot_longer(proportion.I:abundance.III) %>% # convert to long format
separate(name, into = c("var", "idx")) %>% # get values from column names
pivot_wider(names_from=var, values_from=value) %>% # go back to wide
nest(data=-locations) %>%
mutate(reg = map(data, ~lm(abundance~proportion, .))) %>% # do the regression
mutate(intercept=map_dbl(reg, ~coefficients(.)[1]), # get values form regression
slope=map_dbl(reg, ~coefficients(.)[2]))
这与您提供的值相匹配,但从您的描述来看,您似乎希望以另一种方式进行回归:~lm(proportion~abundance, .)
我们可以使用 base R
在 for
循环中执行此操作。创建一个 NULL
list
,length
等于数据集 ('out') 的行数来存储输出。获取数据集中 'proportion'、'abundance' 列的名称 ('prp'、'abn')。遍历数据集的行序列,提取'prp'、'abn'列,用lm
创建模型,提取系数,赋给list
元素'out'。最后,rbind
list
元素并将其分配给原始数据集中的新列
out <- vector('list', nrow(df))
prp <- names(df)[startsWith(names(df), "proportion")]
abn <- names(df)[startsWith(names(df), "abundance")]
for(i in seq_len(nrow(df))) out[[i]] <- coef(lm(abundance ~ proportion,
data.frame(abundance = unlist(df[i, abn]), proportion = unlist(df[i, prp]))))
df[c('slope', 'intercept')] <- do.call(rbind, out)[,2:1]
df[, c("slope", "intercept")]
# slope intercept
#1 -1613.9597 313.7648
#2 -601.7193 241.6664
#3 -329.6502 215.6954
我正在尝试计算数据框中不同列中每一行的斜率和截距。输出(截距和斜率)应作为新列添加到原始数据框中。
为了尽可能清楚地说明我要实现的目标,我在下面提供了一些数据:
locations<-c("a","b","c")
proportion.I<-c(0.073846154, 0.079710145, 0.063218391)
proportion.II<-c(0.049773659, 0.033756955, 0.011237956)
proportion.III<-c(0.090322581, 0.100917431, 0.08051443)
abundance.I<-c(331,331,331)
abundance.II<-c(178,178,178)
abundance.III<-c(87,87,87)
output.slope<-c(5.539e-05, -4.665e-05, -2.819e-05)
output.intercept<-c(5.128e-02, 8.073e-02, 5.726e-02)
df<-data.frame(locations, proportion.I, proportion.II, proportion.III, abundance.I, abundance.II, abundance.III, output.slope, output.intercept)
*我的线性回归的 'dependent' 变量将是 'Proportion'(行 2:4),预测变量(或自变量)将是 'abundance'(行 5:7).
好吧,您的数据不是“整齐”的格式,这使得使用大多数内置函数变得困难。您可以使用 dplyr
和 tidyr
将您的数据转换为一个共享,以便更轻松地进行分组回归。例如
library(dplyr)
library(tidyr)
df %>%
select(-starts_with("output")) %>% #drop "answers"
pivot_longer(proportion.I:abundance.III) %>% # convert to long format
separate(name, into = c("var", "idx")) %>% # get values from column names
pivot_wider(names_from=var, values_from=value) %>% # go back to wide
nest(data=-locations) %>%
mutate(reg = map(data, ~lm(abundance~proportion, .))) %>% # do the regression
mutate(intercept=map_dbl(reg, ~coefficients(.)[1]), # get values form regression
slope=map_dbl(reg, ~coefficients(.)[2]))
这与您提供的值相匹配,但从您的描述来看,您似乎希望以另一种方式进行回归:~lm(proportion~abundance, .)
我们可以使用 base R
在 for
循环中执行此操作。创建一个 NULL
list
,length
等于数据集 ('out') 的行数来存储输出。获取数据集中 'proportion'、'abundance' 列的名称 ('prp'、'abn')。遍历数据集的行序列,提取'prp'、'abn'列,用lm
创建模型,提取系数,赋给list
元素'out'。最后,rbind
list
元素并将其分配给原始数据集中的新列
out <- vector('list', nrow(df))
prp <- names(df)[startsWith(names(df), "proportion")]
abn <- names(df)[startsWith(names(df), "abundance")]
for(i in seq_len(nrow(df))) out[[i]] <- coef(lm(abundance ~ proportion,
data.frame(abundance = unlist(df[i, abn]), proportion = unlist(df[i, prp]))))
df[c('slope', 'intercept')] <- do.call(rbind, out)[,2:1]
df[, c("slope", "intercept")]
# slope intercept
#1 -1613.9597 313.7648
#2 -601.7193 241.6664
#3 -329.6502 215.6954