按两列对R中的数据进行排序,但每行交替

Sorting Data in R by two columns but alternating each row

我正在尝试确定 x 或 y 个体(分别由一个唯一的数字表示)彼此占主导地位的次数。我用count来总结数据:

Dominance1<-count(Dominance, c('Dominant', 'Subordinate')) 

数据如下所示:

 >     Dominant Subordinate freq
            5           9   14
            5          10    9
            5          11    4
            5          15    7
            5          18   14
            5          22    6
            5          24    9
            5          26    5
            5          40    8
            5          43    5
            9          10    4
            9          11    6
            9          15    1
            9          18    7
            9          22   14
            9          24    6
            9          25    7
           10          15    1
           10          18    1
           10          22    2
           10          40    1
           10          43    1
           10          75    4

...等等(所有唯一ID为:5,9,10,11,80,15,75,18,85,22,82,24,25,26,86,68 ,79,83,81,77,91,40,87,43,78... 总数据集是 321 行观察到的这些 ID 和观察频率之间的不同关系)。

但我还需要并排查看在“5”从属时“9”占主导地位的次数。是否可以这样排序,让数据变成这样?

 >     Dominant Subordinate freq
          5          9       14
          9          5        0
          5          11       4
          11         5        7

目前只是根据 'Dominant' 列排序。有没有一种方法可以像我上面展示的那样交替,这样我就可以看到 x 对 y 占主导地位的频率,并与 y 对 x 占主导地位的频率进行比较?

这是完整的数据集:

Dom Sub freq
5   9   14
5   10  9
5   11  4
5   15  7
5   18  14
5   22  6
5   24  9
5   26  5
5   40  8
5   43  5
5   75  15
5   77  10
5   78  10
5   80  3
5   81  2
5   82  12
5   83  11
5   85  8
5   87  11
5   91  16
9   10  4
9   11  6
9   15  1
9   18  7
9   22  14
9   24  6
9   25  7
9   26  6
9   40  12
9   43  8
9   75  10
9   77  1
9   79  1
9   80  4
9   82  20
9   85  9
9   87  7
9   91  4
10  15  1
10  18  1
10  22  2
10  40  1
10  43  1
10  75  4
10  78  1
10  79  4
10  80  3
10  81  1
10  87  1
11  10  2
11  26  1
11  40  1
11  43  3
11  77  1
11  80  5
11  85  1
15  18  2
15  22  1
15  43  1
15  77  1
15  78  1
15  79  2
15  81  1
15  83  2
15  85  2
15  87  2
15  91  2
18  22  2
18  24  1
18  78  2
18  79  1
18  80  4
22  24  2
22  40  1
24  10  1
24  18  1
24  22  7
24  26  11
24  75  1
24  78  3
24  79  8
24  81  11
24  83  5
24  86  8
24  91  13
25  5   3
25  9   1
25  10  3
25  11  3
25  15  2
25  18  1
25  22  6
25  24  5
25  26  3
25  40  5
25  43  8
25  75  3
25  77  7
25  78  5
25  79  5
25  80  3
25  81  2
25  82  6
25  83  5
25  85  2
25  87  6
25  91  3
26  10  3
26  11  8
26  18  5
26  22  1
26  40  9
26  43  5
26  77  1
26  78  7
26  80  5
26  83  1
26  85  3
26  91  1
40  10  1
40  15  1
40  22  4
40  25  1
40  75  1
40  80  1
40  81  1
40  83  1
40  85  1
40  87  2
40  91  1
43  18  2
43  22  2
43  24  7
43  40  4
43  75  3
43  77  2
43  79  2
43  80  3
43  82  1
68  5   15
68  9   41
68  10  3
68  11  5
68  15  6
68  18  9
68  22  12
68  24  8
68  25  14
68  26  1
68  40  8
68  43  10
68  75  6
68  77  9
68  78  3
68  79  6
68  80  3
68  81  3
68  82  5
68  83  5
68  85  12
68  86  9
68  87  9
68  91  4
75  10  1
75  15  1
75  18  2
75  22  4
75  24  2
75  26  2
75  40  3
75  77  1
75  78  6
75  79  6
75  80  6
75  81  1
75  82  2
75  87  7
77  5   1
77  15  1
77  18  7
77  22  2
77  24  1
77  40  4
77  78  8
77  79  2
77  80  4
77  81  7
77  82  1
77  85  5
77  87  3
78  10  3
78  11  1
78  15  1
78  18  1
78  40  2
78  43  1
78  83  2
78  86  2
79  5   4
79  9   20
79  15  1
79  18  1
79  26  4
79  68  1
79  75  1
79  77  1
79  78  2
79  80  1
79  81  4
79  82  10
79  83  9
79  85  4
79  91  15
80  22  2
80  43  1
80  78  2
81  5   14
81  9   20
81  10  2
81  18  8
81  22  11
81  25  3
81  26  4
81  43  1
81  68  1
81  75  4
81  77  1
81  78  4
81  79  3
81  80  11
81  82  13
81  83  13
81  85  1
81  86  3
81  87  1
81  91  16
82  10  4
82  15  4
82  18  1
82  22  1
82  24  3
82  26  2
82  40  7
82  43  3
82  77  5
82  78  2
82  80  4
82  83  3
82  85  2
82  87  4
83  9   2
83  10  4
83  11  3
83  15  7
83  18  2
83  22  2
83  25  2
83  26  5
83  43  3
83  68  1
83  75  3
83  77  7
83  78  5
83  80  2
83  81  1
83  82  2
83  85  1
83  87  9
83  91  4
85  10  2
85  11  2
85  15  1
85  18  1
85  22  2
85  26  1
85  40  2
85  43  6
85  75  4
85  78  1
85  79  2
85  80  2
86  5   9
86  9   6
86  10  5
86  11  6
86  15  5
86  18  5
86  22  9
86  25  22
86  26  6
86  40  3
86  43  12
86  68  1
86  75  16
86  77  4
86  78  4
86  79  9
86  80  8
86  82  16
86  83  6
86  85  6
86  87  5
86  91  12
87  10  1
87  77  1
87  80  4
87  85  1
91  10  4
91  11  3
91  18  5
91  22  1
91  24  1
91  26  2
91  40  1
91  43  1
91  75  3
91  77  4
91  80  2
91  82  9
91  85  8
91  87  8

dplyr 中的 summarisegroup_by 函数在这里可能会有用:

library(dplyr)

# Creating some data for us to work with: 
x <- round(runif(n = 100, min = 0, max = 10))
y <- round(runif(n = 100, min = 0, max = 10))

df <- data.frame(x,y)

df %>% 
  group_by(x, y) %>%
  summarise(freq= n())

每对唯一的 x 和 y 的频率在 'freq' 列中生成

# A tibble: 65 x 3
# Groups:   x [?]
       x     y   freq
   <dbl> <dbl>  <int>
 1    0.    0.      1
 2    0.    2.      1
 3    0.    4.      1
 4    0.    5.      1
 5    0.    7.      1
 6    1.    2.      3
 7    1.    4.      2
 8    1.    5.      2
 9    1.    6.      2
10    1.    8.      1
# ... with 55 more rows

您是否考虑过将此数据表示为图表以进行检查?如果您只是想确定这些对的位置,它可能会有用(如果您想以编程方式执行此操作则没有那么有用)。您提供的数据没有任何相互关系,因此我们无法在这里挑选出任何相互关系——如果它们确实存在,当您查看图表时,它们就会弹出。但是,也许这会有所帮助:

library(igraph)
Dominance1 <- read.table("local copy of data",header=TRUE)
g <- graph.data.frame(Dominance1[,1:2],directed=TRUE)
E(g)$weight <- as.numeric(Dominance1[,3])
plot(g,edge.arrow.size=0.5,edge.curved=0.2,vertex.color="lightblue",
   vertex.size=22,layout=layout_on_grid,edge.color="black")

如果您想在图表上查看权重,可以将 edge.label=E(g)$weight 作为参数添加到 plot

您可以使用 which(which_mutual(g)=="TRUE") 找到具有倒数的节点——因为样本数据中没有匹配项,输出很无聊,但是当您在完整数据集上 运行 它应该为你拿出你所有的互助。

> E(g)[which(which_mutual(g)=="FALSE")]  # edges where there are no mutuals
+ 23/23 edges from 998a30d (vertex names):
 [1] 5 ->9  5 ->10 5 ->11 5 ->15 5 ->18 5 ->22 5 ->24 5 ->26 5 ->40 5 ->43 9 ->10 9 ->11
[13] 9 ->15 9 ->18 9 ->22 9 ->24 9 ->25 10->15 10->18 10->22 10->40 10->43 10->75

> E(g)[which(which_mutual(g)=="TRUE")]  # edges where there ARE mutuals
+ 0/23 edges from 998a30d (vertex names):

我知道这是解决您的问题的一种侧面方法,但希望它可能有点用处!

感谢您发布完整的数据集!更新如下:

library(igraph)
Dom <- read.table("localcopyofdata.txt",header=TRUE)
g <- graph.data.frame(Dom[,1:2],directed=TRUE)
E(g)$weight <- as.numeric(Dom[,3])

这会生成一个具有 321 个连接的 igraph 对象,您可以通过键入 g 查看这些连接。要进行你想要的排序,我们必须拉出顶点的前半部分+1:

> vertices <- unique(V(g)[1:floor((length(unique(V(g)))/2)+1)])
+ 13/25 vertices, named, from c0101e5:
 [1] 5  9  10 11 15 18 22 24 25 26 40 43 68

(实际上,如果您对具有 vertices <- unique(V(g) 的所有顶点都执行此操作并没有什么坏处——您稍后可以通过任何节点查找连接。)现在我们知道了顶点,我们可以对所有这些应用一个函数,以您可以比较它们的方式提取匹配项。命令为:

lapply(vertices, function(x) E(g)[[inc(x)]])

输出如下所示,每个节点一组:

$`5`
+ 26/321 edges from c0101e5 (vertex names):
    tail head tid hid weight
1      5    9   1   2     14
2      5   10   1   3      9
3      5   11   1   4      4
4      5   15   1   5      7
5      5   18   1   6     14
6      5   22   1   7      6
7      5   24   1   8      9
8      5   26   1  10      5
9      5   40   1  11      8
10     5   43   1  12      5
11     5   75   1  14     15
12     5   77   1  15     10
13     5   78   1  16     10
14     5   80   1  18      3
15     5   81   1  19      2
16     5   82   1  20     12
17     5   83   1  21     11
18     5   85   1  22      8
19     5   87   1  24     11
20     5   91   1  25     16
86    25    5   9   1      3
140   68    5  13   1     15
178   77    5  15   1      1
199   79    5  17   1      4
217   81    5  19   1     14
282   86    5  23   1      9

如果你这样做 results <- lapply(vertices, function(x) E(g)[[inc(x)]]) 那么你可以单独调用任何你想要的节点:

> results$'5'
+ 26/321 edges from c0101e5 (vertex names):
    tail head tid hid weight
1      5    9   1   2     14
2      5   10   1   3      9
3      5   11   1   4      4
... the rest are truncated

现在您可以从 results 创建一个 dplyr-able 数据框(如果您想在另一个数据集上使用它,请务必将 13 更改为 length(results)):

step1 <- capture.output(for(n in 1:13) { for(j in n){print(results[[j]])} })
step2 <- step1[grep("^\d",step1),drop=T]
step3 <- unlist(strsplit(step2,"\s+")) # produces list of 1938 numbers
step4 <- as.data.frame(matrix(unlist(step3), ncol=6, byrow=TRUE), stringsAsFactors=FALSE)
group <- cumsum(c(1, sign(diff(as.numeric(step4$V1)) < 0)))
step5 <- cbind(group,step4[,c(2,3,6)])
names(step5) <- c("Group","Dom","Sub","Weight")

现在您可以用它做 dplyr 事情,例如:

> step5 %>% filter(Group==1)
   Group Dom Sub Weight
1      1   5   9     14
2      1   5  10      9
3      1   5  11      4
4      1   5  15      7
5      1   5  18     14
6      1   5  22      6
... the rest is truncated

希望对您有所帮助!必须有一种更简单的方法来解决这个问题,但我喜欢将其表示为图形让您有机会可视化连接(可能不是针对您的问题,而是针对我遇到的其他问题)。