【问题标题】:How to create a unique identifier ID across columns?如何跨列创建唯一标识符 ID?
【发布时间】:2017-09-28 13:51:35
【问题描述】:

我正在尝试准备用于 R 和 Gephi 中的各种网络可视化应用程序的数据。这些格式需要连接两个数据库的数字标识符。我已经弄清楚了后一部分,但是我无法找到一种简洁的方法来跨数据框中的列创建数字 ID 变量。这是一些可复制的代码,说明了我正在尝试做的事情。

org.data <- data.frame(source=c('bob','sue','ann','john','sinbad'),
       target=c('sinbad','turtledove','Aerosmith','bob','john'))

desired.data <- data.frame(source=c('1','2','3','4','5'),
                       target=c('5','6','7','1','4'))


org.data

  source     target
1    bob     sinbad
2    sue     turtledove
3    ann     Aerosmith
4    john    bob
5    sinbad  john

desired.data

  source target
1    1      5
2    2      6
3    3      7
4    4      1
5    5      4

【问题讨论】:

    标签: r numeric recode


    【解决方案1】:

    这是在原始 data.frame 中未列出的唯一名称上使用 match 的基本 R 方法。

    要替换当前的data.frame,请使用

    org.data[] <- sapply(org.data, match, table=unique(unlist(org.data)))
    

    这里,sapply 循环遍历 org.data 中的变量,并将 match 应用于每个变量。 match 返回表参数中第一个参数的位置。在这里,table 是 org.data 中未列出的唯一元素:unique(unlist(org.data))。在这种情况下,sapply 返回一个矩阵。它被转换为data.frame,通过将[] 附加到org.data[] &lt;- 中的org.data 来替换原始数据。这种构造可以认为是在赋值过程中保留了原始对象的结构。

    要构造一个新的data.frame,使用

    setNames(data.frame(sapply(org.data, match, table=unique(unlist(org.data)))),
             names(org.data))
    

    或者更好,正如 Henrik 建议的那样,首先创建 data.frame 的副本,然后使用第一行代码填充副本,而不是使用 setNamesdata.frame,可能会更容易。

    desired.data <- org.data
    

    这两个都返回

      source target
    1      1      5
    2      2      6
    3      3      7
    4      4      1
    5      5      4
    

    【讨论】:

    • 即使 OP 想要构建一个新的数据框,您也可以创建一个原始数据帧的副本,然后将您的第一个代码的结果分配给该副本。 desired.data &lt;- org.data; desired.data[] &lt;- sapply(org.data, match, table=unique(unlist(org.data))) (从setNames(data.frame( 中拯救你,因为我们必须假设结果迟早会被分配?)。 +1!
    • 感谢@Henrik 的建议。首先创建副本可能会更简单,并且可能会减少中间副本。
    • 谢谢,您介意简单解释一下这里发生了什么吗?
    • @elliot 我添加了一些额外的评论。
    【解决方案2】:

    你可以试试这个:

    org.data[] <- as.numeric(factor(c(as.matrix(org.data)), levels = unique(c(as.matrix(org.data)))))
    org.data
      source target
    1      1      5
    2      2      6
    3      3      7
    4      4      1
    5      5      4
    

    【讨论】:

      【解决方案3】:

      您可以尝试关注。这个想法是使用所有唯一名称的级别来创建因子。

      library(tidyverse)
      org.data %>% 
        mutate(source2 = factor(source, levels=unique(unlist(org.data)) ,  labels=1:length(unique(unlist(org.data))))) %>% 
        mutate(target2 = factor(target, levels=unique(unlist(org.data)) ,  labels=1:length(unique(unlist(org.data)))))
        source     target source2 target2
      1    bob     sinbad       1       5
      2    sue turtledove       2       6
      3    ann  Aerosmith       3       7
      4   john        bob       4       1
      5 sinbad       john       5       4
      

      【讨论】:

        【解决方案4】:

        转换为因子,然后转换为整数。

        org.data <- data.frame(source=c('bob','sue','ann','john','sinbad'),
                               target=c('sinbad','turtledove','Aerosmith','bob','john'))
        
        # need to make sure that columns are characters, not factors
        org.data$source <- as.character(org.data$source)
        org.data$target <- as.character(org.data$target)
        
        # define possible values that cover the two columns
        levels <- unique(c(org.data$source, org.data$target))
        
        # factorize, then cast to integer
        org.data$source <- as.integer(factor(org.data$source, levels=levels))
        org.data$target <- as.integer(factor(org.data$target, levels=levels))
        
        org.data
        

        【讨论】:

          猜你喜欢
          • 2014-01-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多