3

次のようなデータフレームがあります。

  message.id sender recipient
1          1      A         B
2          1      A         C
3          2      A         B
4          3      B         C
5          3      B         D
6          3      B         Q

これを取得するために、送信者と受信者の列の値の数で要約したいと思います。

  address messages.sent messages.received
1       A             3                 0
2       B             3                 2
3       C             0                 2
4       D             0                 1
5       Q             0                 1

magrittr私は動作するコードを持っていますが、それは面倒です。以下にあるものではなく、これをすべて1つのチェーンで行う方法があることを願っています:

df <- data.frame(message.id = c(1,1,2,3,3,3),
                 sender = c("A","A","A","B","B","B"),
                 recipient = c("B","C","B","C","D","Q"))
sent <- df %>% 
  group_by(sender) %>%
  summarise(messages.sent = n()) %>%
  mutate(address = sender) %>%
  select(address, messages.sent)

received <- df %>% 
  group_by(recipient) %>%
  summarise(messages.received = n()) %>%
  mutate(address = recipient) %>%
  select(address, messages.received)

df_summary <- merge(sent, received, all = TRUE) %>%
  replace(is.na(.), 0)
4

4 に答える 4

6

使用できますmelt/dcast

library(reshape2)
dcast(melt(df1, id.var='message.id'), value~variable, 
                 value.var='message.id', length)

またはラッパーを使用してrecast

recast(df1, id.var='message.id', value~variable, length)
#    value sender recipient
#1     A      3         0
#2     B      3         2
#3     C      0         2
#4     D      0         1
#5     Q      0         1

使用する必要がある場合dplyr/tidyr

library(dplyr)
library(tidyr)
gather(df1, messages, address, 2:3) %>%
          group_by(messages, address) %>%
          summarise(n=n()) %>% 
          spread(messages, n, fill=0)
#     address sender recipient
#     (chr)  (dbl)     (dbl)
#1       A      3         0
#2       B      3         2
#3       C      0         2
#4       D      0         1
#5       Q      0         1
于 2016-01-01T03:54:54.430 に答える
3

ある種のネットワーク分析を行っている場合は、igraphパッケージを使用すると便利な場合があります

library(igraph)

g <- graph_from_data_frame(dat[c(2:3)])

data.frame(address = V(g)$name,
           sent    = degree(g, mode="out"),
           rec     = degree(g, mode="in"))

#   address sent rec
# A       A    3   0
# B       B    3   2
# C       C    0   2
# D       D    0   1
# Q       Q    0   1

igraphそのようなものが好きなら、パイピングもサポートします

また、ここにベースRの取り組みがあります(あなたが望むものではないことはわかっています))

lvs <- unique(unlist(dat[2:3])) 
sapply(dat[2:3], function(x) table(factor(x, levels=lvs)))
于 2016-01-01T04:41:08.730 に答える
2

dplyr と tidyr を使用すると、次のことができます。

library(dplyr)
library(tidyr)
df <- data.frame(message.id = c(1,1,2,3,3,3),
                 sender = c("A","A","A","B","B","B"),
                 recipient = c("B","C","B","C","D","Q"), stringsAsFactors = FALSE)
df %>% gather(sender, recipient, -message.id) %>% group_by(recipient) %>% summarise(messages.sent = sum(sender == 'sender'), messages.received = sum(sender == 'recipient'))

Source: local data frame [5 x 3]

  recipient messages.sent messages.received
      (chr)         (int)             (int)
1         A             3                 0
2         B             3                 2
3         C             0                 2
4         D             0                 1
5         Q             0                 1
> 

次のように、最初の列名を目的の名前に変更できます。

names(df)[1] <- 'address'
于 2016-01-01T06:51:46.173 に答える
0

aggregateベース R からandを使用する代替手段merge。最後に、NA を削除し、目的の列名で列の名前を変更します。

summary <- merge(aggregate(message.id ~ sender, data = df, length), 
                  aggregate(message.id ~ recipient, data = df, length), 
                  by.x = "sender", 
                  by.y = "recipient", 
                  all = TRUE)
summary[is.na(summary)] <- 0
colnames(summary) <- c("address", "sent", "received")
summary

出力:

  address sent received
1       A    3        0
2       B    3        2
3       C    0        2
4       D    0        1
5       Q    0        1
于 2016-01-02T15:27:59.773 に答える