是否有R函数用于组合不匹配列上的数据帧?

时间:2019-09-18 16:44:45

标签: r date dataframe aggregate transform

我正在尝试根据几个变量对数据框进行排序。

在我的数据框中,我有ID号(id),该人的电话计划的名称(计划),当他们从该计划开始时(start_date),某人切换计划的次数(count_switch),关于该计划的评论者在致电客户服务期间(评论)和评论日期(comment_date)。

要获得此数据框,我加入了两个数据框。其中一个具有id,plan,start_date和count_switch。因此,如果一个人一次切换计划,他们将有两行(一排用于他们开始的地方,一排用于他们切换到的地方)。另一个数据框具有id,comment和comment_date。

我在“ id”上加入了两个数据框。

这是我期望得到的,例如,如果某人一次交换计划,然后在第一个计划中打电话三遍,第二个计划两次时打电话:

id plan start_date count_switch comment comment_date
1   A   8/1/2018       1         Hi         8/3/2018
1   A   8/1/2018       1         Hello      9/1/2018
1   A   8/1/2018       1         Bad        12/22/2018
1   B   1/1/2019       2         Bye        2/1/2019
1   B   1/1/2019       2         Cool       3/1/2019

相反,这就是我得到的:

id plan start_date count_switch comment comment_date
1   A   8/1/2018       1         Hi         8/3/2018
1   A   8/1/2018       1         Hello      9/1/2018
1   A   8/1/2018       1         Bad        12/22/2018
1   A   8/1/2018       1         Bye        2/1/2019
1   A   8/1/2018       1         Cool       3/1/2019
1   B   1/1/2019       2         Hi         8/3/2018
1   B   1/1/2019       2         Hello      9/1/2018
1   B   1/1/2019       2         Bad        12/22/2018
1   B   1/1/2019       2         Bye        2/1/2019
1   B   1/1/2019       2         Cool       3/1/2019

我不确定如何获取信息,因此我知道当某人发表特定评论时,他们会根据其起始日期和评论日期制定特定计划。我希望以此方式进行设置,以便我可以跟踪更改计划前后的评论类型。

这是我第一次在这里发布-很抱歉,这很久了!

非常感谢您的帮助。

谢谢:)

2 个答案:

答案 0 :(得分:0)

不是最漂亮的代码,但是我相信这可以完成您打算要做的事情。

您当前仅使用公共id列进行合并。但是,merge()不知道comment值是属于plan 'A'还是'B',因此它假定最坏的情况并为每个{{1 }}值。您还需要指定在哪个计划下生成plan值。

comment用于读取问题中包含的少量数据(您不需要此软件包)。首先,两个data.table::fread()对象中的所有日期都更改为data.frame对象。然后,在第一个Date中,我使用data.frame添加了一个end_date列,供以后进行逻辑比较。在所有tibble::add_column()start_date值都在过去的意义上,我假设数据是“真实的”。最后,我将comment_date值与comment_datestart_date值进行了比较,以确定每个end_date在哪个plan下制造。然后可以将所得的comment对象与data.frame组合。

merge()

运行这段代码给了我...

library(data.table)
library(tibble)
df1 <- fread(
  'id plan start_date count_switch
    1   A   8/1/2018       1
    1   B   1/1/2019       2')
df1$start_date <- as.Date(df1$start_date, "%m/%d/%Y")
df1 <- add_column(
  df1,
  end_date = c(df1$start_date[2:nrow(df1)], Sys.Date()),
  .after = 'start_date'
)
df2 <- fread(
  'id comment comment_date
    1 Hi         8/3/2018
    1 Hello      9/1/2018
    1 Bad        12/22/2018
    1 Bye        2/1/2019
    1 Cool       3/1/2019')
df2$comment_date <- as.Date(df2$comment_date, "%m/%d/%Y")
df2 <- add_column(
  df2,
  plan = df1$plan[
    sapply(
      df2$`comment_date`, 
      function(x) {
        which(df1$start_date < x & x < df1$end_date)
      }
    )
  ],
  .after = 'id'
)
merge(df1, df2)

答案 1 :(得分:0)

这是使用dplyr的替代方法,我发现它更容易理解。

创建示例数据:

library(dplyr)

df1 <- data.frame("id" = c(1,1), "plan" = c("A","B"),
                  "start_date" = c("8/1/2018", "1/1/2019"),
                  "count_switch" = c(1,2)) 
df1$start_date <- as.Date(df1$start_date, "%m/%d/%Y")

df2 <- data.frame("id" = c(1,1,1,1,1),
                  "comment" = c("Hi", "Hello", "Bad", "Bye", "Cool"),
                  "comment_date" = c("8/3/2018", "9/1/2018", "12/22/2018", "2/1/2019", "3/1/2019")) 
df2$comment_date <- as.Date(df2$comment_date, "%m/%d/%Y") 

现在,我们在end_date中创建一个新的df1列:

df1 <- df1 %>% 
  group_by(id) %>% 
  mutate(end_date = lead(start_date, order_by = id)) %>% 
  ungroup()

df1
#>      id plan  start_date count_switch end_date   
#> 1     1 A     2018-08-01            1 2019-01-01
#> 2     1 B     2019-01-01            2 NA

现在,我们可以像您一样合并数据帧,但是然后进行过滤,以使注释日期在start_dateend_date之间(或者end_dateNA ):

df <- merge(x=df1, y=df2, by="id") %>% 
  filter(comment_date >= start_date,
         (comment_date < end_date) | is.na(end_date))

df
#>   id plan start_date count_switch   end_date comment comment_date
#> 1  1    A 2018-08-01            1 2019-01-01      Hi   2018-08-03
#> 2  1    A 2018-08-01            1 2019-01-01   Hello   2018-09-01
#> 3  1    A 2018-08-01            1 2019-01-01     Bad   2018-12-22
#> 4  1    B 2019-01-01            2       <NA>     Bye   2019-02-01
#> 5  1    B 2019-01-01            2       <NA>    Cool   2019-03-01