【问题标题】:Arrange rows by pairs in R based on two columns基于两列在R中成对排列行
【发布时间】:2018-05-23 13:19:03
【问题描述】:

我需要按发送消息的用户对排序数据表。目前,数据如下所示:

我想重新排列行,以便查看用户之间交换了多少消息。如果一个用户发送了一条消息,但另一个用户没有回复,我需要在 Messages_sent 列中设置一个值 0。

下一步,我需要计算两个用户之间的对话长度,因此,每两行求和 Messages_sent。

请指教如何重新排列数据表!

【问题讨论】:

  • 您好,如果您将数据作为文本而不是图像包含在内,对您的帮助会容易得多。至于问题本身,还不是很清楚。例如,如果您的系统中只有 2 位用户,那么您希望在这 2 种情况下的输出中看到什么:一位用户发送 5 条消息,另一位用户回复 3 条。一位用户发送 3 条消息,另一位未回复。您希望在这两种情况下查看多少条记录以及每个字段中应包含哪些记录?
  • 嗨!我希望每对通信的用户有两行。在一行中,您可以看到一个用户向另一个用户发送了多少条消息,在第二行中则相反。在某些情况下,消息已发送,但用户没有回复。在这种情况下,其中一行的值为 0。
  • @Katia,我尝试了以下方法,但它不起作用: for (i in 1:nrow(dt.messages)) { dt.messages$message_received[i]
  • 嗨 Yuliia,我添加了一些解决此问题的建议。

标签: r datatable


【解决方案1】:

使用 dplyr,要获得描述中给出的表格,此代码应该可以工作。但是,如果您想将两个方向的计数相加,则第一行包含您可能想要的所有内容。

df <- merge(df,df
  ,by.x=c("from_id","to_id"),by.y=c("to_id","from_id")
  ,all.x=TRUE,all.y=TRUE)
df <- mutate(df,Messages_sent.x=coalesce(Messages_sent.x,0),
                Messages_sent.y=coalesce(Messages_sent.y,0))
df$row <- 1:nrow(df)
rbind(select(df,-Messages_sents.y) %>%
        rename(Messages_sent=Messages_sent.x),
      select(df,-Messages_sent.x) %>% 
        rename(Messages_sent=Messages_sent.y,from_id=to_id,to_id=from_id)
     ) %>% arrange(row) %>% select(-row)

【讨论】:

    【解决方案2】:

    以下是使用基本 R 函数的步骤:

    df <- data.frame(from_id=c(624227,624227,624227,624227,624227,624227,667255,667255,667255,7134655,713465),
                     to_id = c(352731,693915,184455,771100,503940,91558,626814,857601,862512,156874,419242),
                     message_sent=c(1,6,2,1,1,1,2,7,3,1,1))
    
    # merge dataset together with itself swapping from_id and to_id columns 
    df.full <- merge(df,df, by.x=c("from_id","to_id"), by.y=c("to_id","from_id"),suffixes = c(".x",".y"), all=TRUE)
    
    # fill missing values with 0
    # those records will correspond to all the pairs where 
    # someone did not send any messages back
    df.full[is.na(df.full)] <- 0
    
    # calculate total number of messages for each pair:
    df.full$total <- df.full$message_sent.x + df.full$message_sent.y
    
    head(df.full)
    #   from_id   to_id message_sent.x message_sent.y total
    # 1   91558  624227              0              1     1
    # 2  156874 7134655              0              1     1
    # 3  184455  624227              0              2     2
    # 4  352731  624227              0              1     1
    # 5  419242  713465              0              1     1
    # 6  503940  624227              0              1     1
    

    对于非常大的数据集,在这种情况下,基本 R 函数可能会很慢,您可以考虑使用 dplyr 库(对于此处的大多数步骤,它具有类似的功能):

    library(dplyr)
    df.full.2 <- merge(df,df               # merge dataframe and switched one
                ,by.x=c("from_id","to_id"),by.y=c("to_id","from_id")
                ,all.x=TRUE,all.y=TRUE) %>%
      mutate(message_sent.x=coalesce(message_sent.x,0),     # replace NAs with 0
             message_sent.y=coalesce(message_sent.y,0)) %>%
      mutate(total=rowSums(.[3:4]))        # calculate total number of messages
    
    head(df2.full.2)
    #  from_id   to_id message_sent.x message_sent.y total
    #1   91558  624227              0              1     1
    #2  156874 7134655              0              1     1
    #3  184455  624227              0              2     2
    #4  352731  624227              0              1     1
    #5  419242  713465              0              1     1
    #6  503940  624227              0              1     1
    

    如果需要成对的记录彼此跟随很重要,您还可以添加以下代码:

    df2.full.3 <- df2.full.2 %>% 
      mutate(pair.id=sprintf("%06d%6d",pmin(from_id,to_id ),
                                       pmax(from_id,to_id ))) %>%
      arrange(pair.id) %>% select(-pair.id)
    
    head(df2.full.3)
    #  from_id   to_id message_sent.x message_sent.y total
    #1   91558  624227              0              1     1
    #2  624227   91558              1              0     1
    #3  156874 7134655              0              1     1
    #4 7134655  156874              1              0     1
    #5  184455  624227              0              2     2
    #6  624227  184455              2              0     2
    

    还有一个 data.table 包,对于非常大的数据集也非常有效:

    library(data.table)
    # convert dataframe to datatable
    setDT(df)
    df.full <- merge(df,df, by.x=c("from_id","to_id"), by.y=c("to_id","from_id"),
                     suffixes = c(".x",".y"), all=TRUE)
    
    # substitute NAs with zeros
    for (j in 3:4)set(df.full,which(is.na(df.full[[j]] )),j,0)
    
    # calculate the total number of messages
    df.full[, total:=message_sent.x+message_sent.y]
    head(df.full)
    #    from_id   to_id message_sent.x message_sent.y total
    # 1:   91558  624227              0              1     1
    # 2:  156874 7134655              0              1     1
    # 3:  184455  624227              0              2     2
    # 4:  352731  624227              0              1     1
    # 5:  419242  713465              0              1     1
    # 6:  503940  624227              0              1     1
    

    根据数据集的大小,其中一种方法可能比其他两种方法更有效。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-23
      • 2022-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-10
      相关资源
      最近更新 更多