【问题标题】:Finding paired events with reshape使用 reshape 查找配对事件
【发布时间】:2015-04-07 22:46:28
【问题描述】:

我有一个用户和他们在特定时间购买的物品的列表,我想从原始数据中生成这些对的列表。虽然我可以并且可能会编写一个小的 Python 脚本来执行此操作,但我觉得 reshape(或更可能是 reshape2)包可以在几行内完成此操作。

在代码中,我希望将下面的 df 数据框转换为 resdf 数据框:

df <- data.frame(user=c("u1","u2","u1","u3","u2","u4","u5","u4"),
                 item=c("i1","i1","i2","i3","i2","i3","i3","i4"),
                 time=c(1,1,2,3,4,4,5,6))
> df
  user item time
1   u1   i1    1
2   u2   i1    1
3   u1   i2    2
4   u3   i3    3
5   u2   i2    4
6   u4   i3    4
7   u5   i3    5
8   u4   i4    6
> 

### some reshape code here

resdf <- data.frame(user=c("u1","u2","u4"),
                    item1=c("i1","i1","i3"),
                    item2=c("i2","i2","i4"),
                    time=c(1,1,4),
                    delt=c(1,3,2))
> pdf
  user item1 item2 time delt
1   u1    i1    i2    1    1
2   u2    i1    i2    1    3
3   u4    i3    i4    4    2

是否有任何重塑向导可以帮助我解决这个问题?

【问题讨论】:

  • 用户u4u5 的期望输出在哪里?
  • u3 和 u5 将为空,因为他们只购买了一件商品,因此没有要生成的对。 Delt 是事件之间的时间差异。但我并不太担心,一旦我弄清楚如何生成对,应该很容易。
  • 优秀。我将使用一些大型数据集(近 500 万个事件)对它们进行尝试,并将解决方案授予效果最好的那个。
  • 这两个答案对我来说都非常有用,但是合并解决方案可以立即且完全没有警告地工作,而 dcast 解决方案更难理解并且有很多警告和 NA(也必须使用全名 dcast.data.table 以使其与我的库一起使用)。但是我怀疑 dcast 解决方案对于非常大的数据集可能会更好,因为它使用的是数据表。如果你不介意的话,可以多研究一下。

标签: r reshape reshape2


【解决方案1】:

这是使用dplyr的解决方案:

library(dplyr)

df %>%
  group_by(user) %>%
  filter(n() == 2) %>%
  arrange(time) %>%
  summarise(
    item1 = first(item),
    item2 = last(item),
    delt = last(time) - first(time),
    time = first(time)
    ) %>%
  select(user, item1, item2, time, delt)

【讨论】:

    【解决方案2】:

    这是我使用 data.table 包的尝试(它也有一个 dcast 函数)

    library(data.table)
    setkey(setDT(df), user, item) # sorting by user and time so `head` and `diff` will work
    df[, `:=`(indx = paste0("item", seq_len(.N)), # Creating all the needed variables
              indx2 = .N,
              time2 = head(time, 1),
              delt = diff(time)), 
         user]
    
    dcast(df[indx2 > 1L], # Decasting by the modified item column
                  user + time2 + delt ~ indx, 
                  value.var = "item")
    
    #    user time2 delt item1 item2
    # 1:   u1     1    1    i1    i2
    # 2:   u2     1    3    i1    i2
    # 3:   u4     4    2    i3    i4
    

    【讨论】:

      【解决方案3】:

      如果您将具有重复 user 值的行合并回没有重复值的行,您将获得所需的信息,然后稍作按摩即可获得所需的排列:

      > merge(df[!duplicated(df$user), ], df[duplicated(df$user), ], by="user")
        user item.x time.x item.y time.y
      1   u1     i1      1     i2      2
      2   u2     i1      1     i2      4
      3   u4     i3      4     i4      6
      > inter <- merge(df[!duplicated(df$user), ], df[duplicated(df$user), ], by="user")
      > inter$delt <- inter$time.y-inter$time.x
      > inter[ , c(1,2,4,3,6)]
        user item.x item.y time.x delt
      1   u1     i1     i2      1    1
      2   u2     i1     i2      1    3
      3   u4     i3     i4      4    2
      

      【讨论】:

      • 这是一个不错且简单的解决方案。好主意。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多