R 函数创建一个矩阵,该矩阵填充一个数字在表中显示的次数,但仅当另一列是唯一的时

R 函数创建一个矩阵,该矩阵填充一个数字在表中显示的次数,但仅当另一列是唯一的时,r,matrix,count,data-manipulation,R,Matrix,Count,Data Manipulation,这可能是一个复杂的问题。我有一个数据帧X,其中包含粒子、源和汇列。我的目标是创建一个矩阵,其中行是源编号,列是汇编号。如果粒子数对于源/汇组合是唯一的,则应使用每个源数出现汇数的次数填充矩阵 数据框如下所示: 预期输出应如下所示: 您可以看到源1中的粒子1在汇1中被发现两次,但仅计数一次。然而,来自源1的粒子1在汇4中找到,因此它也被计算在第4列下。如果在同一源/汇组合中多次发现粒子,则仅对其计数一次。但是,如果在同一来源的多个汇中发现该粒子,则仍会对其进行计数 我曾尝试使用这个独特的函数,

这可能是一个复杂的问题。我有一个数据帧X,其中包含粒子、源和汇列。我的目标是创建一个矩阵,其中行是源编号,列是汇编号。如果粒子数对于源/汇组合是唯一的,则应使用每个源数出现汇数的次数填充矩阵

数据框如下所示:

预期输出应如下所示:

您可以看到源1中的粒子1在汇1中被发现两次,但仅计数一次。然而,来自源1的粒子1在汇4中找到,因此它也被计算在第4列下。如果在同一源/汇组合中多次发现粒子,则仅对其计数一次。但是,如果在同一来源的多个汇中发现该粒子,则仍会对其进行计数

我曾尝试使用这个独特的函数,但在正确计算它时遇到了极大的困难。我想创建一个函数来实现这一点

我添加了另一个示例,其中添加了一行。数据框X中突出显示的值将导致新矩阵中突出显示的值。这里的想法是,由于粒子数不同,它会添加一个,但粒子数1在接收器1中出现两次,因此不会被计数两次。

除了在同一个接收器中不计算粒子两次外,如果粒子数是唯一的,我还需要计算来自同一源的粒子进入接收器的次数

编辑:新数据

structure(list(Location = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 
1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), 
    Particle = c(1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 
    4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L), Time = c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), Long = c(272.302, 272.302, 
    272.302, 272.302, 278.695, 278.695, 278.695, 278.695, 277.323, 
    279.544, 279.12, 279.085, 279.766, 277.323, 272.302, 279.766, 
    279.544, 278.754, 279.12, 279.845, 279.766, 272.302, 272.302, 
    279.766), Lat = c(17.14, 17.14, 17.14, 17.14, 24.681, 24.681, 
    24.681, 24.681, 27.612, 27.865, 28.997, 24.87, 27.419, 27.612, 
    17.141, 27.419, 27.865, 24.679, 28.997, 27.37, 27.419, 17.141, 
    17.141, 27.419), Depth = c(NA_integer_, NA_integer_, NA_integer_, 
    NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
    NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
    NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
    NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
    NA_integer_), Distance.x = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 
    0L, 100L, 200L, 300L, 50L, 200L, 300L, 500L, 400L, 300L, 
    450L, 350L, 400L, 300L, 200L, 300L, 600L), Source = c(1L, 
    1L, 1L, 1L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 
    1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L), Sink = c(1L, 1L, 1L, 1L, 
    3L, 3L, 3L, 3L, 6L, 7L, 8L, 4L, 5L, 6L, 1L, 5L, 7L, 3L, 8L, 
    5L, 5L, 1L, 1L, 5L)), row.names = c(NA, -24L), class = "data.frame")
我使用的代码:

Dummy_Data_Con_Table <-
  Dummy_Data %>%
  select(Source, Sink, Location, Particle) %>%
  group_by(Sink,Source) %>%
  summarise(unique = n_distinct(Particle, Location)) %>%
  distinct() %>%
  right_join(expand.grid(Source= 1:8,Sink =1:8)) %>%
  replace_na(list(unique = 0)) %>%
  pivot_wider(id_cols = Source, names_from = Sink, names_prefix = "Sink", values_from = unique)
唯一的区别是,我还添加了粒子和位置的组合必须是唯一的规定。我在几周前使用了这个代码,它很有效。我不知道是什么改变了它。

基本的R方法:

mat <- matrix(rep(0, 64), ncol = 8)
mat[as.matrix(df)] <- 1
或使用tidyverse:

输出

输出

编辑:

修正后的数据和基础R,也可以考虑如下:

df$source = factor(df$source, levels = 1:8)
df$sink = factor(df$sink, levels = 1:8)

df2 <- aggregate(particle ~ source + sink, df, function(x) length(unique(x)))

xtabs(particle ~ source + sink, data = df2)
资料


欢迎来到堆栈溢出!如果你能提供一个reprex,那就真的很有帮助了:我想确保我是对的:你的矩阵的1,1条目中有一个1,即使组合source=1,sink=1出现了两次。这是因为source=1,sink=4也出现了,还是所有这些数字都只是平展到1?我问你是因为你的第一段让人觉得这是第一个原因,但是你的段落正好在预期输出之后,这似乎是第二个原因。矩阵的1,1处有一个1,尽管它发生了两次,因为数据帧X的粒子列中的值在两个实例之间是相同的。这对我的原始示例有效。但是,如果粒子数是唯一的,我需要函数将1添加到矩阵中。我添加了一个更新的示例来演示这个问题。已经有一段时间了,但我刚刚回来尝试了代码,您慷慨地提供了。这给了我一个新的错误,我不知道为什么。它说:Error:by required,因为数据源没有公共变量。然而,我没有改变任何事情。这是一个正确连接的问题。你知道这可能是什么吗?我已经尝试解组,这样可能接收器和源变量将再次可见,但没有效果。谢谢。我添加了我正在使用的数据和代码。我编辑了一些东西,比如选择我需要的列,添加位置和粒子必须唯一的刺激。几周前,当我测试这个的时候,这些都起作用了。一定是我对数据帧做了一些小动作来破坏代码。我就是想不出来。@asnead94谢谢-我只是用你的虚拟数据和代码试了一下,它对我来说很好,没有错误。你试过重新启动R吗?清洁会议?升级软件包,例如tidyverse/other?我刚刚重新启动了R会话,并使用了相同的降价单元,它成功了。我不知道发生了什么事。我应该记得有时候只是把它关掉再打开。
library(tidyverse)

df$unique = 1

expand.grid(source = 1:8, sink = 1:8) %>%
  left_join(distinct(df)) %>%
  replace_na(list(unique = 0)) %>%
  pivot_wider(id_cols = source, names_from = sink, names_prefix = "Sink", values_from = unique)
# A tibble: 8 x 9
# Groups:   source [8]
  source Sink1 Sink2 Sink3 Sink4 Sink5 Sink6 Sink7 Sink8
   <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1      1     1     0     0     1     0     0     0     0
2      2     1     0     1     0     0     1     0     0
3      3     0     0     1     1     0     0     1     0
4      4     0     0     0     1     1     1     0     0
5      5     0     0     1     1     0     0     1     0
6      6     0     0     1     0     0     0     0     1
7      7     1     0     1     0     1     0     0     0
8      8     0     0     0     0     1     0     0     0
df %>%
  group_by(sink, source) %>%
  summarise(unique = n_distinct(particle)) %>%
  distinct() %>%
  right_join(expand.grid(source = 1:8, sink = 1:8)) %>%
  replace_na(list(unique = 0)) %>%
  pivot_wider(id_cols = source, names_from = sink, names_prefix = "Sink", values_from = unique)
# A tibble: 8 x 9
  source Sink1 Sink2 Sink3 Sink4 Sink5 Sink6 Sink7 Sink8
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1      1     1     0     0     1     0     0     0     0
2      2     1     0     1     0     0     1     0     0
3      3     0     0     1     1     0     0     2     0
4      4     0     0     0     1     1     1     0     0
5      5     0     0     1     1     0     0     1     0
6      6     0     0     1     0     0     0     0     1
7      7     1     0     1     0     1     0     0     0
8      8     0     0     0     0     1     0     0     0
df$source = factor(df$source, levels = 1:8)
df$sink = factor(df$sink, levels = 1:8)

df2 <- aggregate(particle ~ source + sink, df, function(x) length(unique(x)))

xtabs(particle ~ source + sink, data = df2)
df <- data.frame(
  particle = c(1:7, 1:7, 1:9),
  source = c(1:7,1:7,1:8,3),
  sink = c(1,1,4,6,7,8,5,4,6,7,5,4,8,3,1,3,3,4,3,3,1,5,7)
)