Why does iterative 1:1 matching give different results then real k:1 matching? I assume my understanding of propensity score matching using R's matchit package is wrong.
MatchIt has a ratio argument where I can specifiy k:1 matchings. I did a 2:1 matching with the lalonde dataset which gives me in result  185 treated and 370 controlls.
In another variante I did 1:1 matching but in two iterations. So in first step I pulled the first 185 best machtes, removed them from the original/source data and pulled the next 185 best matches.
My assumption was that the result would be the same. But it isn't.
> a = sort(rownames_from_ratio_matching)
> b = sort(rownames_from_two_iterations_matching)
> table(a == b)

FALSE  TRUE 
  326    44

> table(a %in% b)

FALSE  TRUE 
    7   363 

What is the reason behind this? I assume there is a statistical reason and not a technical one.
Minimal working example
library("MatchIt")
data("lalonde")

# 2:1 matching
m.out1 <- matchit(
    treat ~ age + educ + race + married + nodegree + re74 + re75,
    data = lalonde,
    method = "nearest",
    distance = "glm",
    ratio = 2
)
df_out1 = match.data(m.out1)


## First 1:1 matching
m.out2 <- matchit(
    treat ~ age + educ + race + married + nodegree + re74 + re75,
    data = lalonde,
    method = "nearest",
    distance = "glm"
)
df_out2 = match.data(m.out2)
# row names of treated matches
treated2 = rownames(df_out2[df_out2$treat == 0,])
# remove the treated matches form the original data frame
lalonde <- lalonde[!(row.names(lalonde) %in% treated2),]


## Second 1:1 matching
m.out3 <- matchit(
    treat ~ age + educ + race + married + nodegree + re74 + re75,
    data = lalonde,
    method = "nearest",
    distance = "glm"
)
df_out3 = match.data(m.out3)
treated3 = rownames(df_out3[df_out3$treat == 0,])

rownames_from_ratio_matching = rownames(df_out1[df_out1$treat == 0,])
rownames_from_two_iterations_matching = c(treated2, treated3)

# unexpected FALSE
all(sort(rownames_from_ratio_matching) == sort(rownames_from_two_iterations_matching))


This is because when you run the second round of 1:1 matching (i.e., m.out3), you are estimating a new propensity score using only those who were not matched in in the first round of 1:1 matching (i.e., m.out2). In contrast, when doing 2:1 matching, everyone is matched using one set of propensity scores. This creates differences in who is matched.
There are two ways to prevent this: 1) compute a propensity score beforehand and supply that propensity score to each call to matchit(), being sure to remove the previously matched cases between m.out2 and m.out3; and 2) using the discard option in m.out3 to drop previously matched units in the matching but include them in the propensity score estimation. The second method is easier; all you have to do is add
discard = m.out2$treat == 0 & m.out2$weights > 0

to the call to m.out3 <- matchit(). This prevents any control units who were previously matched from being matched again, but includes them in the propensity score. You also need to retain the original dataset, i.e., not remove any units from lalonde because discard is doing all the work of removing the previously matched units. Doing this does give the right answer.
all(sort(rownames_from_ratio_matching) == sort(rownames_from_two_iterations_matching))
[1] TRUE

It might also be a good idea to estimate the propensity score beforehand anyway so that it doesn't need to be estimated twice; you can also add
distance = m.out2$distance

in the call to m.out3 <- matchit() to reuse the propensity scores from m.out2. You still need to include the discard option.
