否则,如果循环在R中运行非常缓慢

否则,如果循环在R中运行非常缓慢,r,R,我正在进行一项研究项目,研究使人们更有可能投票的因素,重点是人们离投票站的距离。我需要数百万个人的完整选民登记和选民历史记录。有几种方式可以让某人投票(亲自投票、缺席投票、提前投票或临时投票)或不投票(未登记、登记但未投票或无投票资格)。我的数据中有一列(29)是关于某人在特定选举中的投票情况。NULL表示未注册,V表示亲自注册等 对于回归分析,我想为每种投票人类型创建一个不同的列(1表示是,0表示否,列号68-74),并为是否有人投票创建另一个1/0列(数字75)。我在下面编写的代码应该可以做

我正在进行一项研究项目,研究使人们更有可能投票的因素,重点是人们离投票站的距离。我需要数百万个人的完整选民登记和选民历史记录。有几种方式可以让某人投票(亲自投票、缺席投票、提前投票或临时投票)或不投票(未登记、登记但未投票或无投票资格)。我的数据中有一列(29)是关于某人在特定选举中的投票情况。NULL表示未注册,V表示亲自注册等

对于回归分析,我想为每种投票人类型创建一个不同的列(1表示是,0表示否,列号68-74),并为是否有人投票创建另一个1/0列(数字75)。我在下面编写的代码应该可以做到这一点,但它在我的计算机上运行得非常慢,一个小时后甚至无法到达第1000行。除了速度,它工作得很好。我已经被批准使用我大学的超级计算机*,但我想找出一个更快的算法。我的笔记本电脑和超级计算机上都有R和STATA,我很乐意使用它们

dcv.new <- read.csv("VoterHist.csv", header=TRUE)
# I previously set columns 68-75 to default to 0
for(i in 1:nrow(dcv.new))
{
  if(is.na(dcv.new[i,29]))
  {
    dcv.new[i,69] <- 1
  }
  else if(dcv.new[i,29]=="V")
  {
    dcv.new[i,68] <- 1
    dcv.new[i,75] <- 1
  }
  else if(dcv.new[i,29]=="A")
  {
    dcv.new[i,70] <- 1
    dcv.new[i,75] <- 1
  }
  else if(dcv.new[i,29]=="N")
  {
    dcv.new[i,71] <- 1
  }
  else if(dcv.new[i,29]=="E")
  {
    dcv.new[i,72] <- 1
  }
  else if(dcv.new[i,29]=="Y")
  {
    dcv.new[i,73] <- 1
  }
  else if(dcv.new[i,29]=="P")
  {
    dcv.new[i,74] <- 1
    dcv.new[i,75] <- 1
  }
  else if(dcv.new[i,29]=="X")
  {
    dcv.new[i,74] <- 1
    dcv.new[i,75] <- 1
  }
}

dcv.new您应该将代码矢量化。忘了这么多的“如果”

dcv.new[is.na(dcv.new[,29]),69] <- 1
dcv.new[dcv.new[,29] == "V", c(68, 75)] <- 1

dcv.new[is.na(dcv.new[,29]),69]R基本上是矢量化的,所以寻找矢量化操作来代替循环。在这种情况下,可以对每个操作进行矢量化,使其作用于整个矩阵,而不是单个行

以下是您的
if
else
语句的前三条:

dcv.new[is.na(dcv.new[,29]), 69] <- 1
dcv.new[dcv.new[,29]=="V", c(68,75)] <- 1
dcv.new[dcv.new[,29]=="A", c(70,75)] <- 1
....
当我们使用公式符号拟合模型时,我们可以:

mod <- lm(response ~ voterType, data = dcv.new)
请注意,大多数采用公式的建模函数(如上图所示)的工作方式与我在下文中所述相同。您不限于
lm()
型号。

这里有一个小例子

set.seed(42)
dcv.new <- data.frame(response = rnorm(20),
                      voterType = sample(c("V","A","N","E","Y","P","X",NA), 20, 
                                         replace = TRUE))
head(dcv.new)

> head(dcv.new)
    response voterType
1  1.3709584         E
2 -0.5646982         E
3  0.3631284         V
4  0.6328626      <NA>
5  0.4042683         E
6 -0.1061245      <NA>
生成基础矩阵代数和QR分解所需的协变矩阵。上面的代码给出了一个小示例:

> model.matrix(~ voterType, data = dcv.new)
   (Intercept) voterTypeE voterTypeN voterTypeP voterTypeV voterTypeX
1            1          1          0          0          0          0
2            1          1          0          0          0          0
3            1          0          0          0          1          0
5            1          1          0          0          0          0
8            1          0          0          1          0          0
10           1          0          0          0          0          0
11           1          0          1          0          0          0
12           1          0          1          0          0          0
13           1          1          0          0          0          0
14           1          0          0          0          0          1
15           1          0          0          0          1          0
16           1          0          0          1          0          0
17           1          0          0          1          0          0
18           1          0          0          0          0          0
19           1          0          1          0          0          0
20           1          0          0          0          0          0
   voterTypeY
1           0
2           0
3           0
5           0
8           0
10          1
11          0
12          0
13          0
14          0
15          0
16          0
17          0
18          0
19          0
20          1
attr(,"assign")
[1] 0 1 1 1 1 1 1
attr(,"contrasts")
attr(,"contrasts")$voterType
[1] "contr.treatment"
这就是您希望对代码执行的操作。因此,如果您真的需要它,您可以使用
model.matrix()
来生成矩阵,因为您不需要这些属性

在这种情况下,参考水平为
“A”

它由
model.matrix
输出中的
(Intercept)
列表示。请注意,这些处理与参考水平的偏差代码形成对比。您可以通过添加
-1
(0r
+0
)来抑制公式中的截距,从而获得伪值:


你的问题不在于算法,而在于你在,因为你不是在写R代码,你是在写C代码或其他什么。我已经详细介绍了如何进行向量化,以及你应该如何在R中进行回归。一般来说,对于使用公式接口的回归模型或其他东西,您不需要自己形成协变量矩阵,您可以让R的公式解析代码为您完成这项工作。Stata被简要地提到,但是线程并没有按照Stata解决方案进行开发,所以Stata标签对于将来的搜索来说只是无关紧要的。如果发帖人想看到Stata解决方案,最好是重新发布,但要详细解释Stata数据集结构、变量名称等。本质上,还有更简单的方法来管理Stata中的数据。(STATA是一个拼写错误。)你可能想引用
V
@GavinSimpson的话,谢谢你发现了这个错误。我只是简单地键入
model.matrix(~x-1,dat)
作为这个问题的答案+这就是他真正想要的(如何将一个向量转换成一个由0和1组成的稀疏矩阵)。我真的很欣赏他的回答。当时我是个新手,在过去的四年里,我学到了很多东西,这主要归功于互联网上友好的人们。
set.seed(42)
dcv.new <- data.frame(response = rnorm(20),
                      voterType = sample(c("V","A","N","E","Y","P","X",NA), 20, 
                                         replace = TRUE))
head(dcv.new)

> head(dcv.new)
    response voterType
1  1.3709584         E
2 -0.5646982         E
3  0.3631284         V
4  0.6328626      <NA>
5  0.4042683         E
6 -0.1061245      <NA>
mod <- lm(response ~ voterType, data = dcv.new)
summary(mod)
> mod <- lm(response ~ voterType, data = dcv.new)
> summary(mod)

Call:
lm(formula = response ~ voterType, data = dcv.new)

Residuals:
    Min      1Q  Median      3Q     Max 
-2.8241 -0.4075  0.0000  0.5856  1.9030 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)  
(Intercept)   -2.656      1.425  -1.864   0.0952 .
voterTypeE     2.612      1.593   1.639   0.1356  
voterTypeN     3.040      1.646   1.847   0.0978 .
voterTypeP     2.742      1.646   1.666   0.1300  
voterTypeV     2.771      1.745   1.588   0.1468  
voterTypeX     2.378      2.015   1.180   0.2684  
voterTypeY     3.285      1.745   1.882   0.0925 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 

Residual standard error: 1.425 on 9 degrees of freedom
  (4 observations deleted due to missingness)
Multiple R-squared: 0.3154, Adjusted R-squared: -0.1411 
F-statistic: 0.6909 on 6 and 9 DF,  p-value: 0.6635 
model.matrix( ~ voterType, data = dcv.new)
> model.matrix(~ voterType, data = dcv.new)
   (Intercept) voterTypeE voterTypeN voterTypeP voterTypeV voterTypeX
1            1          1          0          0          0          0
2            1          1          0          0          0          0
3            1          0          0          0          1          0
5            1          1          0          0          0          0
8            1          0          0          1          0          0
10           1          0          0          0          0          0
11           1          0          1          0          0          0
12           1          0          1          0          0          0
13           1          1          0          0          0          0
14           1          0          0          0          0          1
15           1          0          0          0          1          0
16           1          0          0          1          0          0
17           1          0          0          1          0          0
18           1          0          0          0          0          0
19           1          0          1          0          0          0
20           1          0          0          0          0          0
   voterTypeY
1           0
2           0
3           0
5           0
8           0
10          1
11          0
12          0
13          0
14          0
15          0
16          0
17          0
18          0
19          0
20          1
attr(,"assign")
[1] 0 1 1 1 1 1 1
attr(,"contrasts")
attr(,"contrasts")$voterType
[1] "contr.treatment"
> with(dcv.new, levels(voterType)[1])
[1] "A"
> model.matrix(~ voterType - 1, data = dcv.new)
   voterTypeA voterTypeE voterTypeN voterTypeP voterTypeV voterTypeX voterTypeY
1           0          1          0          0          0          0          0
2           0          1          0          0          0          0          0
3           0          0          0          0          1          0          0
5           0          1          0          0          0          0          0
8           0          0          0          1          0          0          0
10          0          0          0          0          0          0          1
11          0          0          1          0          0          0          0
12          0          0          1          0          0          0          0
13          0          1          0          0          0          0          0
14          0          0          0          0          0          1          0
15          0          0          0          0          1          0          0
16          0          0          0          1          0          0          0
17          0          0          0          1          0          0          0
18          1          0          0          0          0          0          0
19          0          0          1          0          0          0          0
20          0          0          0          0          0          0          1
attr(,"assign")
[1] 1 1 1 1 1 1 1
attr(,"contrasts")
attr(,"contrasts")$voterType
[1] "contr.treatment"