【问题标题】:I need to create unique word pairs either in R or excel我需要在 R 或 excel 中创建唯一的单词对
【发布时间】:2019-02-05 14:10:26
【问题描述】:

我有 2 个城市名称列表。两个列表都包含完全相同的城市名称。我必须从这些列表中创建城市对。例如,第一个列表包含伦敦、巴黎、莫斯科、日内瓦和东京等名称。清单 2 包含完全相同的名称。但是,第三个列表应该包含“London-Paris”、“London-Tokyo”、“London-Geneva”等对,但不能包含“Tokyo-London”或“Paris-London”,因为这会重复计算。任何 R 或 excel 中的帮助将不胜感激。

我曾尝试在 R 中使用“combn”函数。但是我有大约 4500 个观察结果,“combn”函数对我不起作用。

【问题讨论】:

  • 同城可以成对吗?例如“伦敦-伦敦”
  • 不知道为什么@utubun 删除了他的答案,但combn(myList, 2, paste, collapse = "-") 效果很好。
  • @avid_user 我在考虑 4500 个城市,以及 combn 完成这项工作需要多少时间。取消删除。
  • 另外,不知道为什么这个问题有 3 票“太宽泛”。虽然对某些人来说可能微不足道,但这个问题有一个明确的目标、预期的输入和输出。我唯一要添加的是 OP 尝试过的代码。如果是重复的,请将其标记为一个。 “太宽泛”不是恕我直言的好理由。
  • 检查这个问题以获得比combn更快的方法:stackoverflow.com/questions/26828301/faster-version-of-combn

标签: r excel


【解决方案1】:

(你真的不需要第二个列表来做到这一点,一个就足够了)

cities  <- list("London", "Paris", "Kyiv", "Geneva", "Tokyo")

combn(cities, 2, paste, collapse = "-")

# [1] "London-Paris"  "London-Kyiv"   "London-Geneva" "London-Tokyo"  "Paris-Kyiv"   
# [6] "Paris-Geneva"  "Paris-Tokyo"   "Kyiv-Geneva"   "Kyiv-Tokyo"    "Geneva-Tokyo" 

【讨论】:

  • 比我的 expand.grid 解决方案简单得多!
  • 谢谢@Tom。我的第一个想法是使用expand.grid,不知何故我错过了问题的最后一句话。
【解决方案2】:

使用expand.grid然后操作:

# create all possible combinations
df <- expand.grid(myList, myList)

# ensure only 1 combination for each pair
df <- as.data.frame(unique(t(apply(df, 1, sort))))

# remove same city combinations
df <- subset(df, df$V1 != df$V2)

# create column with pairs
df$combo <- paste0(df$V1, "-", df$V2)

【讨论】:

    【解决方案3】:

    您也可以在 excel 中执行此操作。创建一个新模块,粘贴以下代码,更新前2行代码中的范围并执行VBA宏:

    Sub combn_VBA()
        'Define variables
        Dim CityListSourceRange As Range: Set CityListSourceRange = Sheet1.Range("A1:A5") '<-- Replace A5:A9 with range address containing the city names
        Dim CityCombinationDestinyRange As Range: Set CityCombinationDestinyRange = Sheet1.Range("C1") '<-- Replace C1 with first cell where you want to place the result list
        Set CityList = CreateObject("Scripting.Dictionary")
    
        'Copies the source cities into a collection
        For Each CellX In CityListSourceRange
            i = i + 1
            CityList.Add CellX.Value, i
        Next CellX
    
        'Creates unique pairs
        For Each City1 In CityList
            For Each City2 In CityList
                If CityList(City1) < CityList(City2) Then
                    CityCombinationDestinyRange.Offset(j, 0).Value = City1 & "-" & City2
                    j = j + 1
                End If
            Next City2
        Next City1
    End Sub
    

    要获得这样的东西:

    【讨论】:

      【解决方案4】:

      对于Excel - VBA

      我们可以使用一个小技巧:

      由于列表是相同的,我们可以只用一个列表来解决问题:

      Sub MakePairs()
          Dim i As Long, N As Long, k As Long, j As Long
      
          N = Cells(Rows.Count, "A").End(xlUp).Row
          k = 1
      
          For i = 1 To N - 1
              For j = i + 1 To N
                  Cells(k, 3).Value = Cells(i, 1).Value & "-" & Cells(j, 1).Value
                  k = k + 1
              Next j
          Next i
      End Sub
      

      注意:

      1. 此技术可避免现有对的不必要排列
      2. 这种技术避免了像 London-London 这样的重复对

      【讨论】:

        【解决方案5】:

        我们可以尝试编写自己的函数来查找城市名称的组合它的工作速度略快,与combn()相比:

        功能

        combn2 <- function(x){
          n = length(x)
          paste(
            x[rep.int(seq_along(x)[-n], times = rev(seq_along(x))[-1])], 
            x[unlist(lapply(seq_along(x)[-1], ':', to = n))], 
            sep = '-'
          )
        }
        

        检查结果是否正确

        cities  <- list("London", "Paris", "Kyiv", "Geneva", "Tokyo")
        
        combn2(cities)
        
        # [1] "London-Paris"  "London-Kyiv"   "London-Geneva" "London-Tokyo"  "Paris-Kyiv"   
        # [6] "Paris-Geneva"  "Paris-Tokyo"   "Kyiv-Geneva"   "Kyiv-Tokyo"    "Geneva-Tokyo" 
        

        比较 5K 城市的 combn()combn2() 的时间

        数据
        cities <- unique(maps::world.cities$name)
        
        length(cities)
        
        # [1] 41074
        
        cities <- cities[1:5000]
        
        combn() 的时间
        system.time(
          combn(cities, 2, paste, collapse = "-")
        )
        
        #   user  system elapsed 
        # 116.02    0.01  116.33 
        
        combn2() 的时间安排
        system.time(
          combn2(cities)
        )
        
        #  user  system elapsed 
        # 14.04    0.00   14.09 
        

        我认为大部分时间都花在paste() 上,所以如果你找到核化paste() 的方法,如果你能告诉我你是怎么做到的,我将不胜感激。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-06-19
          • 1970-01-01
          • 2018-12-08
          • 1970-01-01
          相关资源
          最近更新 更多