【问题标题】:create a scoring matrix from two dataframes从两个数据帧创建一个评分矩阵
【发布时间】:2012-01-05 20:49:50
【问题描述】:

我正在尝试比较存储在两个数据帧(foobar)中的变量集(X)。每个X 是一个唯一的自变量,最多有10 个Y 值与之关联。我想通过比较它们共有的Y 值的数量来比较每个 foo.X 和每个 bar.X - 所以输出可能是一个矩阵,其轴的长度为 foo.x 乘以 bar.x。

这个简单的 foo 和 bar 示例想要返回一个 2x2 矩阵,比较 a,b 和 c,d:

foo <- data.frame(x= c('a', 'a', 'a', 'b', 'b', 'b'), y=c('ab', 'ac', 'ad', 'ae', 'fx', 'fy'))
bar <- data.frame(x= c('c', 'c', 'c', 'd', 'd', 'd'), y=c('ab', 'xy', 'xz', 'xy', 'fx', 'xz'))

编辑:


我将以下代码留给其他新手学习(for 循环是有效的,但可能非常次优),但下面的两个解决方案是有效的。特别是 Ramnath 对 data.table 的使用在处理非常大的数据帧时非常有效。

使用 stack 函数将数据帧存储为 y 值的列表

foo.list <- dlply(foo, .(x), function(x) stack(x, select = y))
bar.list <- dlply(bar, .(x),function(x)  stack(x, select = y))

编写一个函数来比较两个堆叠列表中的成员关系

comparelists <- function(list1, list2) {
  for (i in list1){ 
    for (j in list2){
      count <- 0
      if (i[[1]] %in% j[[1]]) count <- count + 1
    }
  }
  return count
  }

写一个输出矩阵

output.matrix <- matrix(1:length(foo.list), 1:length(bar.list))
for (i in foo.list){
  for (j in bar.list){
    output.matrix[i,j] <- comparelists(i,j)

    }

}

【问题讨论】:

    标签: r dataframe data.table


    【解决方案1】:

    必须有一百种方法来做到这一点;这是我感觉相对简单的一个:

    library(reshape2)
    foo <- data.frame(x = c('a', 'a', 'a', 'b', 'b', 'b'), 
                      y = c('ab', 'ac', 'ad', 'ae', 'fx', 'fy'))
    bar <- data.frame(x = c('c', 'c', 'c', 'd', 'd', 'd'), 
                      y = c('ab', 'xy', 'xz', 'xy', 'fx', 'xz'))
    
    # Create a function that counts the number of common elements in two groups
    nShared <- function(A, B) {
        length(intersect(with(foo, y[x==A]), with(bar, y[x==B])))
    }
    
    # Enumerate all combinations of groups in foo and bar
    (combos <- expand.grid(foo.x=unique(foo$x), bar.x=unique(bar$x)))
    #   foo.x bar.x
    # 1     a     c
    # 2     b     c
    # 3     a     d
    # 4     b     d
    
    # Find number of elements in common among all pairs of groups
    combos$n <- mapply(nShared, A=combos$foo.x, B=combos$bar.x)
    
    # Reshape results into matrix form
    dcast(combos, foo.x ~ bar.x)
    #   foo.x c d
    # 1     a 1 0
    # 2     b 0 1
    

    【讨论】:

    • 不错!我看到你扩展到一个大网格,计算重叠然后重铸。优雅的。但是如果 foo 和 bar 实际上有数千个成员呢?你会改变你的方法吗?
    • 除非计算速度真的很慢,否则我不会更改它。但我认为这应该可以很好地扩展到更大的数据集。
    • 感谢乔希。我在 R 中足够新,没有使用过 intersect、expand.grid、dcast 或 mapply - 所以除了快速回答之外,这是一个真正的帮助!
    • 在组合 (或 0-length row.names) 。在使用我的真实数据集时,我遇到了类似的问题。
    • data.frames 的列可能属于character 类而不是factor,因此levels() 对它们不起作用。我已经编辑了答案,将levels() 替换为unique()。它现在应该适用于字符列和因子列。
    【解决方案2】:

    这是使用merge的更简单方法

    library(reshape2)
    df1 <- merge(foo, bar, by = 'y')
    dcast(df1, x.x ~ x.y, length)
    
      x.x c d
    1   a 1 0
    2   b 0 1
    

    编辑。使用data.table 可以更快地合并。这是代码

    foo_dt <- data.table(foo, key = 'y')
    bar_dt <- data.table(bar, key = 'y')
    df1 <- bar_dt[foo_dt, nomatch = 0]
    

    【讨论】:

    • 感谢@ramnath - 这确实是一个非常优雅和简单的解决方案。不幸的是,当我将其应用于整个数据集时,这个人也会使我的计算机崩溃。我想我将回到我使用 python 处理数据的 pre-R 策略(我遍历数据并将结果写入文件,这样计算机就不会出现故障),然后使用 R 进行绘图能力。
    • foobar 有多大,它们包含多少层?
    • 检查我的编辑。它使用data.table 来执行merge,因此非常有效。你能检查一下这对你有用吗?如果该步骤是瓶颈,我正在尝试找出cast 数据的有效方法。
    • 哇。使用数据表要快得多。我的foobar 的长度约为 55k 和 1.5M。我还没有尝试在全长数据帧上进行投射,因为我认为 dables 加入的方式可能有些有趣。
    • data.table 太棒了!结果表的 dcast 非常快,现在我可以专注于转换/拆分/子集,以满足我的心愿。感谢您花时间向我展示此方法。我总是对 Stack Overflow 社区印象深刻!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-22
    • 1970-01-01
    • 2017-12-17
    • 1970-01-01
    • 2021-04-10
    • 2019-09-23
    • 1970-01-01
    相关资源
    最近更新 更多