我正在尝试根据几个变量对数据框进行排序。
在我的数据框中,我有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
我不确定如何获取信息,因此我知道当某人发表特定评论时,他们会根据其起始日期和评论日期制定特定计划。我希望以此方式进行设置,以便我可以跟踪更改计划前后的评论类型。
这是我第一次在这里发布-很抱歉,这很久了!
非常感谢您的帮助。
谢谢:)
答案 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_date
和start_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_date
和end_date
之间(或者end_date
是NA
):
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