在 R 中对数据帧进行双重循环(使用 Levenshtein Dist 将行相互比较)的最聪明方法



我在几条记录上煮了一个 paramString 的 df:

             idName                                          Str
1         Аэрофлот_Эконом 95111000210102121111010100111000100110101001
2        Аэрофлот_Комфорт 95111000210102121111010100111000100110101001
3         Аэрофлот_Бизнес 96111000210102121111010100111000100110101001
4       Трансаэро_Дисконт 26111000210102120000010100001010000010001000
5 Трансаэро_Туристический 26111000210002120000010100001010000010001000
6        Трансаэро_Эконом 26111000210002120000010100001010000010001000

现在我需要将每个与其他与 levenshtainDist 进行比较,它作为一个函数 (str1,str2) 工作,所以我显然需要双循环。但是,我很确定应该有一种简洁的矢量化(apply/lapply/sapply)方法来做到这一点,但是我找不到任何类似的解决方案......

该函数adist计算广义的列文施泰因距离。这就是你需要的吗?

假设您的数据位于 data.frame 中,使用 : adist(mydf$Str) 将返回一个矩阵,其中包含每对Str列之间的距离。

由于您有一个 data.frame,我认为进行双循环的最佳方法是 lapply/sapply 双循环,它适用于data.frames

例如:

df1 <- data.frame(a=1:20,b=1:20) #example dataframe
a <- data.frame(lapply(1:nrow(df1), function(x) {
                  sapply(1:nrow(df1), function(y) {
                    sum( df1[x,2], df1[y,2]) #I just add the two cells (I only use the second column here for the demonstration) / replace with your function
                  }
                  )
                } 
                )
    )
colnames(a) <- 1:20 #change names

第一个lapply将返回nrow(df1)列表,每个列表内将是一个nrow(df1)观察向量(函数的评估)。这意味着您将拥有一个nrow(df1) x nrow(df1)列表,可以像我上面所做的那样非常方便地转换为data.frame。因此,您有一个nrow(df1) x nrow(df1) data.frame

以上输出:

> str(a)
'data.frame':   20 obs. of  20 variables:
 $ 1 : int  2 3 4 5 6 7 8 9 10 11 ...
 $ 2 : int  3 4 5 6 7 8 9 10 11 12 ...
 $ 3 : int  4 5 6 7 8 9 10 11 12 13 ...
 $ 4 : int  5 6 7 8 9 10 11 12 13 14 ...
 $ 5 : int  6 7 8 9 10 11 12 13 14 15 ...
 $ 6 : int  7 8 9 10 11 12 13 14 15 16 ...
 $ 7 : int  8 9 10 11 12 13 14 15 16 17 ...
 $ 8 : int  9 10 11 12 13 14 15 16 17 18 ...
 $ 9 : int  10 11 12 13 14 15 16 17 18 19 ...
 $ 10: int  11 12 13 14 15 16 17 18 19 20 ...
 $ 11: int  12 13 14 15 16 17 18 19 20 21 ...
 $ 12: int  13 14 15 16 17 18 19 20 21 22 ...
 $ 13: int  14 15 16 17 18 19 20 21 22 23 ...
 $ 14: int  15 16 17 18 19 20 21 22 23 24 ...
 $ 15: int  16 17 18 19 20 21 22 23 24 25 ...
 $ 16: int  17 18 19 20 21 22 23 24 25 26 ...
 $ 17: int  18 19 20 21 22 23 24 25 26 27 ...
 $ 18: int  19 20 21 22 23 24 25 26 27 28 ...
 $ 19: int  20 21 22 23 24 25 26 27 28 29 ...
 $ 20: int  21 22 23 24 25 26 27 28 29 30 ...

您甚至可以将其添加到函数中,并采用通用的双循环方式。

附言请记住,使用族apply的任何功能都不是矢量化的,但比for-loop更好。

另一种方法是计算要比较的行的组合,然后使用"mapply"。 我假设您想一次比较矩阵中的两行:

# get combinations
cbn <- combn(nrow(your_data), 2)  # take 2 at a time
ans <- mapply(dist_function
            , your_data[cbn[1, ], 1]
            , your_data[cbn[2, ], 1]
            )

最新更新