Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R data.table按两列分组和迭代_R_Group By_Iteration_Data.table - Fatal编程技术网

R data.table按两列分组和迭代

R data.table按两列分组和迭代,r,group-by,iteration,data.table,R,Group By,Iteration,Data.table,我是R的新手,正在尝试解决以下问题: 有一个表,其中有两列图书和读者,其中图书和读者分别是图书和读者ID: > books = c (1,2,3,1,1,2) > readers = c(30, 10, 20, 20, 10, 30) > bt = data.table(books, readers) > bt books readers 1: 1 30 2: 2 10 3: 3 20 4: 1

我是R的新手,正在尝试解决以下问题:

有一个表,其中有两列
图书
读者
,其中
图书
读者
分别是图书和读者ID:

> books = c (1,2,3,1,1,2)
> readers = c(30, 10, 20, 20, 10, 30)
> bt = data.table(books, readers)
> bt
   books readers
1:     1      30
2:     2      10
3:     3      20
4:     1      20
5:     1      10
6:     2      30
对于每一对书,我需要使用以下算法计算阅读这两本书的读者数量:

for each book
  for each reader of the book
    for each other_book in books of the reader
      increment common_reader_count ((book, other_book), cnt)
为了实现上述算法,我需要将这些数据分成两个列表:1)包含每本书读者的图书列表和2)包含每名读者阅读的图书的读者列表,例如:

> bookList = list( 
+ list(1, list(30, 20, 10)),
+         list(2, list(10, 30)),
+         list(3, list(20))
+       )
> 
> readerList = list (
+ list(30, list(1,2)),
+ list(20, list(3,1)),
+ list(10, list(2,1))
+ )
>  
问题:

1) 使用什么函数从book表构建这些列表

2) 从
bookList
readerList
如何根据阅读这两本书的读者数量生成书对?对于上述
bt
book表,结果应为:

((1, 2), 2)
((1,3), 1)
((2,3), 0)  
books | 1 | 2 | 3 |
   1  | 1 | 2 | 1 |
   2  | 2 | 1 | 0 |
   3  | 1 | 0 | 1 |

   Which means:

   book 1 and 2 are read together by 2 readers 
   book 1 and 3 are read together by 1 reader
   book 2 and 3 are read together by 0 readers
两本书的顺序并不重要,因此,例如
(1,2)
(2,1)
应减少为其中一本

请建议函数和数据结构来解决此问题。谢谢

更新:

理想的结果是,我需要得到一个矩阵,其中图书id为行和列。交叉点是一对阅读两本书的读者数。因此,对于上述示例,矩阵应为:

((1, 2), 2)
((1,3), 1)
((2,3), 0)  
books | 1 | 2 | 3 |
   1  | 1 | 2 | 1 |
   2  | 2 | 1 | 0 |
   3  | 1 | 0 | 1 |

   Which means:

   book 1 and 2 are read together by 2 readers 
   book 1 and 3 are read together by 1 reader
   book 2 and 3 are read together by 0 readers
如何构建这样的矩阵?

尝试以下方法:

## gives you a seperate list for each book
list_bookls <- split(bt$readers, books)

## gives you a seperate list for each reader
list_readers <- split(bt$books, readers)
关于你问题的第二部分,我将使用以下内容:

bt2 <- bt[ , .N, by = .(readers, books)]
library(tidyr)
spread(bt2, key = books, value = "N", fill = 0)

这里有一个base R解决方案来测试这些对是否被读取。如果您确实需要使用,其他人可以为
数据表添加一个:

books = c (1,2,3,1,1,2)
readers = c(30, 10, 20, 20, 10, 30)
bks = data.frame(books, readers)

cmb <- combn(unique(books), 2)
cmb <- t(cmb)
combos <- as.data.frame(cmb)
bktbl <- t(table(bks))

for (i in 1:nrow(bktbl)) {
  x[i] <- sum(bktbl[i, cmb[i, 1]], bktbl[i, cmb[i, 2]])
  combos$PairRead <- ifelse(x > 1,"yes", "no")
}
combos
  V1 V2 PairRead
1  1  2      yes
2  1  3      yes
3  2  3       no
books=c(1,2,3,1,1,2)
读卡器=c(30,10,20,20,10,30)
bks=data.frame(书籍、阅读器)

cmb这里是另一个选项:

combs <- combn(unique(books), 2)# Generate combos of books
setkey(bt, books)
both.read <-bt[                 # Cartesian join all combos to our data
  data.table(books=c(combs), combo.id=c(col(combs))), allow.cartesian=T
][,
  .(                            # For each combo, figure out how many readers show up twice, meaning they've read both books
    read.both=sum(duplicated(readers)), 
    book1=min(books), book2=max(books)
  ),
  by=combo.id
]
dcast.data.table(               # dcast to desired format
  both.read, book1 ~ book2, value.var="read.both", fun.aggregate=sum
)

请注意,通过设计,这只会产生非等效的组合(即,我们不显示书籍1-2和2-1,仅显示1-2,因为它们是相同的)。

您的
data.table code
不会产生与基函数相同的结果。我知道,这就是为什么我编写了“输出为data.table时相同”,第二种形式更有意义,但是OP提到希望输出为列表..布局并没有什么不同。提供的信息不同。你是对的,我编辑它是为了让它更清楚,谢谢!我认为更多使用数据的方法在这里是有用的,因为OP说“请建议函数和数据结构来解决这个问题。谢谢!”很好。我在写一个表达式,看看是否按照OP的要求阅读了不同的书籍组合。请看我的问题更新-我需要两本书一起阅读的次数,而不是标志
read_together
1-1、2-2、3-3不应该是每本书的阅读人数(即分别为3、2、1)?当提供代码时,如果它可以复制粘贴就更好了,你知道,在行首没有
+
。看起来很棒,谢谢!我是R新手,所以对使用的函数有点不知所措。在何处阅读有关
allow.cartesian
dcast
?有关
allow.cartesian
的信息,请参阅
?数据表
。有关
dcast
的信息,请参见
dcast.data.table
重塑2::dcast
。此外,为了更容易理解,请分别运行每个步骤(即运行
bt[data.table(books=c(combs),combo.id=c(col(combs)),allow.cartesian=T]
首先,然后添加下一步,等等。如果你能口头描述你的解决方案背后的想法,包括中间步骤,就更容易理解整个问题。我试图从代码中理解每个单独的步骤,但如果不清楚每一步应该实现什么,就很难理解。谢谢这里要解释的是re。也许你可以从阅读intro data.table开始
   book1 2 3
1:     1 2 1
2:     2 0 0