[英]R Storing regression coefficients in data frame column by group
我有一個包含調查結果的數據框。 結果以垂直格式存儲。 數據框看起來像這樣-
set.seed(1000)
df = data.frame(RESP_ID=c(rep(1,6),rep(2,8),rep(3,9),rep(4,5),rep(5,4),rep(6,10),rep(7,4),rep(8,8),rep(9,8),rep(10,10)),
CLIENT=c(rep("A",6),rep("A",8),rep("A",9),rep("A",5),rep("A",4),rep("B",10),rep("B",4),rep("B",8),rep("B",8),rep("B",10)),
QST=c(paste0("Q",c(1:6)),paste0("Q",c(1:8)),paste0("Q",c(1:9)),paste0("Q",c(1:5)),paste0("Q",c(1:4)),paste0("Q",c(1:10)),paste0("Q",c(1:4)),paste0("Q",c(1:8)),paste0("Q",c(1:8)),paste0("Q",c(1:10))),
VALUE=round(runif(72,1,4),0))
數據框說明
RESP_ID =受訪者ID。 每個ID通訊員都對應一個響應者。 在此樣本數據框中,我們有10位受訪者。
CLIENT =通訊錄的名稱,即受訪者的客戶名稱。 在此示例數據框中,我們有兩個客戶端(A和B)。
QST =對應於調查中的問題編號。
VALUE =對應於問題的答案選項。 所有問題都有4個答案選項(1至4)。
目的
對於每個客戶和問題組合,我想創建一個單獨的列,該列在QST
列中存儲該問題回歸到Q2的回歸系數。
因此,在回歸模型中, Q2
是因變量,所有其他問題都是自變量。
我的嘗試
我的嘗試沒有給我想要的結果。
slopesdf = df %>%
spread(QST, VALUE, fill = 0) %>%
group_by(CLIENT) %>%
mutate(COEFFICIENT=lm(Q2 ~ .))
我試圖QST
CLIENT
& QST
分組,然后為每個與Q2回歸的問題找到斜率。 我相信有更好的方法可以做到這一點。
目前,我的嘗試給我以下錯誤消息-
mutate_impl(.data,點)中的錯誤:評估錯誤:“。” dans la formule et pas d'argument'data'
所需的輸出
我希望最后一個數據幀包含三列:一列用於CLIENT
,一列用於QST
,第三列稱為COEFFICIENT
,其中CLIENT和QST的每種組合的系數都以Q2作為響應變量進行回歸。
任何幫助,將不勝感激。
我不確定100%是否確定您要得到的輸出,但這是否正確?
df2 <- df %>%
spread(QST, VALUE, fill = 0) %>%
split(.$CLIENT) %>%
lapply(., function(x) { lm(Q2 ~ ., x[, -c(1,2)])$coefficients }) %>%
do.call(rbind, .) %>%
data.frame(.) %>%
mutate(CLIENT = rownames(.)) %>%
gather(QST, COEFFICIENT, -CLIENT) %>%
arrange(CLIENT)
> df2
CLIENT QST COEFFICIENT
1 A X.Intercept. -1.200000e+01
2 A Q1 1.000000e+00
3 A Q10 NA
4 A Q3 2.000000e+00
5 A Q4 3.000000e+00
6 A Q5 5.000000e-01
7 A Q6 NA
8 A Q7 NA
9 A Q8 NA
10 A Q9 NA
11 B X.Intercept. 5.000000e+00
12 B Q1 -1.326970e-16
13 B Q10 1.666667e+00
14 B Q3 3.726559e-15
15 B Q4 -2.000000e+00
16 B Q5 NA
17 B Q6 NA
18 B Q7 NA
19 B Q8 NA
20 B Q9 NA
編輯:
運行拆分組件只會為每個客戶端生成一個寬格式數據幀的列表:
df %>%
spread(QST, VALUE, fill = 0) %>%
split(.$CLIENT)
$A
RESP_ID CLIENT Q1 Q10 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9
1 1 A 4 0 1 4 3 3 2 0 0 0
2 2 A 2 0 2 2 3 2 4 4 3 0
3 3 A 2 0 2 3 3 1 2 4 2 3
4 4 A 3 0 3 4 2 1 0 0 0 0
5 5 A 3 0 4 4 3 0 0 0 0 0
$B
RESP_ID CLIENT Q1 Q10 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9
6 6 B 3 2 3 2 3 2 2 1 3 3
7 7 B 2 0 3 2 2 0 0 0 0 0
8 8 B 3 0 2 4 1 3 3 2 3 0
9 9 B 2 0 1 4 2 1 3 1 2 0
10 10 B 3 2 3 3 3 3 4 2 3 3
請注意,如果您的原始數據沒有值,則所有零填充(如果未回答問題)。 關於這一點,請參閱本博克的答案。
如果現在包括在每個代碼上運行lm
的代碼,您將直接獲得系數值,其中包括上面看到的NA值:
> df %>%
+ spread(QST, VALUE, fill = 0) %>%
+ split(.$CLIENT) %>%
+ lapply(., function(x) { lm(Q2 ~ ., x[, -c(1,2)])$coefficients })
$A
(Intercept) Q1 Q10 Q3 Q4 Q5 Q6 Q7 Q8 Q9
6.6666667 2.0000000 NA -1.6666667 -0.6666667 -1.6666667 NA NA NA NA
$B
(Intercept) Q1 Q10 Q3 Q4 Q5 Q6 Q7 Q8 Q9
13.0 -3.0 -0.5 -2.0 NA 2.0 NA NA NA NA
編輯2:
如果使用此df
,只是為了探索更完整的數據集:
set.seed(42)
df <-
expand.grid(RESP_ID = 1:10,
CLIENT = c("A", "B"),
QST = paste("Q", 1:10, sep = "")) %>%
mutate(VALUE = round(runif(200, 1, 4), 0))
並運行相同的代碼,我們得到沒有NA值的系數:
> df %>%
+ spread(QST, VALUE, fill = 0) %>%
+ split(.$CLIENT) %>%
+ lapply(., function(x) { lm(Q2 ~ ., x[, -c(1,2)])$coefficients }) %>%
+ do.call(rbind, .) %>%
+ data.frame(.) %>%
+ mutate(CLIENT = rownames(.)) %>%
+ gather(QST, COEFFICIENT, -CLIENT) %>%
+ arrange(CLIENT)
CLIENT QST COEFFICIENT
1 A X.Intercept. 6.50000000
2 A Q1 -4.14285714
3 A Q3 2.50000000
4 A Q4 0.85714286
5 A Q5 1.00000000
6 A Q6 -0.64285714
7 A Q7 -1.21428571
8 A Q8 -1.85714286
9 A Q9 2.50000000
10 A Q10 -0.07142857
11 B X.Intercept. -4.69924812
12 B Q1 -0.86466165
13 B Q3 1.56390977
14 B Q4 1.10150376
15 B Q5 -0.86842105
16 B Q6 0.87593985
17 B Q7 0.57142857
18 B Q8 0.25187970
19 B Q9 0.79699248
20 B Q10 -0.12781955
遵循我大腦邏輯的解決方案(我們需要將Q2
作為單獨的變量使用...以這種方式重新排列數據后,我們就可以運行。( NA
值絕對是由於此微小數據集的不足而引起的) -預測變量沒有變化,因此無法估計響應的情況...)
(df
%>% group_by(RESP_ID,CLIENT)
## add a new variable for Q2
%>% mutate(Q2=VALUE[QST=="Q2"])
## drop the old one
%>% filter(QST!="Q2")
%>% group_by(CLIENT,QST)
## run the regression by group; return a data frame
%>% do(as.data.frame(rbind(coef(lm(Q2~VALUE,data=.)))))
## convert wide coefficients to long
%>% tidyr::gather(coef,value,-c(CLIENT,QST))
%>% arrange(CLIENT)
)
對於這樣的任務,我喜歡R for Data Science的“許多模型”方法。 它符合tidyverse樣式,使用嵌套的數據框和purrr::map
創建模型的列表列。 然后broom::tidy
提供實用程序,用於提取您需要的有關模型的信息。
我放下ID列只是為了在數據散布后擺脫它,並由CLIENT
分組和嵌套:
library(tidyverse)
df %>%
spread(key = QST, value = VALUE, fill = 0) %>%
select(-RESP_ID) %>%
group_by(CLIENT) %>%
nest()
#> # A tibble: 2 x 2
#> CLIENT data
#> <fct> <list>
#> 1 A <tibble [5 × 10]>
#> 2 B <tibble [5 × 10]>
之后,創建一列線性模型。 將quick = T
傳遞給broom::tidy
返回模型診斷表的簡化版本; 如果不進行設置,您還將獲得模型中每個變量的標准誤差,測試統計量和p值。
df %>%
spread(key = QST, value = VALUE, fill = 0) %>%
select(-RESP_ID) %>%
group_by(CLIENT) %>%
nest() %>%
mutate(lm_mod = map(data, function(d) lm(Q2 ~ ., data = d))) %>%
mutate(mod_tidy = map(lm_mod, broom::tidy, quick = T)) %>%
unnest(mod_tidy) %>%
head()
#> # A tibble: 6 x 3
#> CLIENT term estimate
#> <fct> <chr> <dbl>
#> 1 A (Intercept) 2.67
#> 2 A Q1 0.333
#> 3 A Q10 NA
#> 4 A Q3 -0.333
#> 5 A Q4 -1.
#> 6 A Q5 1.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.