处理 R 中的分组数据集
Dealing with grouped dataset in R
我有这样的数据集:
+----+-------+---------+----------+--+
| id | time | event | timediff | |
+----+-------+---------+----------+--+
| 1 | 15.00 | install | - | |
| 1 | 15.30 | sale | 00.30 | |
| 1 | 16.00 | sale | 00.30 | |
| 2 | 15.00 | sale | - | |
| 2 | 15.30 | sale | 0.30 | |
| 3 | 16.00 | install | - | |
| 4 | 15.00 | install | - | |
| 5 | 13.00 | install | - | |
| 5 | 14.00 | sale | 01.00 | |
+----+-------+---------+----------+--+
我想清理这个数据集:
我想排除第一个(和接下来的 n..)事件是销售但不是安装的 ID。
我想排除有安装但没有销售的 ID(这些 ID 确实是唯一的)
最终得到如下结果:
+----+-------+---------+----------+
| id | time | event | timediff |
+----+-------+---------+----------+
| 1 | 15.00 | install | - |
| 1 | 15.30 | sale | 0.30 |
| 1 | 16.00 | sale | 0.30 |
| 5 | 13.00 | install | - |
| 5 | 14.00 | sale | 01.00 |
+----+-------+---------+----------+
我如何在 R 中做到这一点?是否有任何特定的数据操作包,或者我可以只使用 if 公式?我应该使用 tapply 吗?
根据示例,我们可以按 'id' 和 filter
对具有 first
元素的 'event' 列进行分组 'install',第二个为 'sale' 以获得预期的输出。
df1 %>%
group_by(id) %>%
filter(first(event)=='install' & event[2L]=='sale')
id time event timediff
# (int) (dbl) (chr) (dbl)
#1 1 15.0 install NA
#2 1 15.3 sale 0.3
#3 1 16.0 sale 0.3
#4 5 13.0 install NA
#5 5 14.0 sale 1.0
或者如果除第一个元素之外的所有元素都应该是 'sale',我们通过将 first
元素与 'install' 进行比较来创建一个逻辑变量 ('ind')连续元素为 'sale'(使用 lead
),然后是 filter
组,其中 all
和 'ind' 为真。如果需要,我们可以使用 select
.
删除 'ind' 列
df1 %>%
group_by(id) %>%
mutate(ind= first(event)=='install' & lead(event, default='sale')=='sale') %>%
filter(all(ind)) %>%
ungroup() %>%
select(-ind)
或者我们可以用data.table
.,按'id'分组,if
行数大于1(.N >1
),第一个元素是'install'(event[1L]=='install'
)和all
其余元素为'sale',则得到Data.table(.SD
).[=26的子集=]
library(data.table)
setDT(df1)[, if(.N > 1 & event[1L]=='install' & all(event[2:.N]=='sale')) .SD, by = id]
# id time event timediff
#1: 1 15.0 install NA
#2: 1 15.3 sale 0.3
#3: 1 16.0 sale 0.3
#4: 5 13.0 install NA
#5: 5 14.0 sale 1.0
我有这样的数据集:
+----+-------+---------+----------+--+ | id | time | event | timediff | | +----+-------+---------+----------+--+ | 1 | 15.00 | install | - | | | 1 | 15.30 | sale | 00.30 | | | 1 | 16.00 | sale | 00.30 | | | 2 | 15.00 | sale | - | | | 2 | 15.30 | sale | 0.30 | | | 3 | 16.00 | install | - | | | 4 | 15.00 | install | - | | | 5 | 13.00 | install | - | | | 5 | 14.00 | sale | 01.00 | | +----+-------+---------+----------+--+
我想清理这个数据集: 我想排除第一个(和接下来的 n..)事件是销售但不是安装的 ID。 我想排除有安装但没有销售的 ID(这些 ID 确实是唯一的)
最终得到如下结果:
+----+-------+---------+----------+ | id | time | event | timediff | +----+-------+---------+----------+ | 1 | 15.00 | install | - | | 1 | 15.30 | sale | 0.30 | | 1 | 16.00 | sale | 0.30 | | 5 | 13.00 | install | - | | 5 | 14.00 | sale | 01.00 | +----+-------+---------+----------+
我如何在 R 中做到这一点?是否有任何特定的数据操作包,或者我可以只使用 if 公式?我应该使用 tapply 吗?
根据示例,我们可以按 'id' 和 filter
对具有 first
元素的 'event' 列进行分组 'install',第二个为 'sale' 以获得预期的输出。
df1 %>%
group_by(id) %>%
filter(first(event)=='install' & event[2L]=='sale')
id time event timediff
# (int) (dbl) (chr) (dbl)
#1 1 15.0 install NA
#2 1 15.3 sale 0.3
#3 1 16.0 sale 0.3
#4 5 13.0 install NA
#5 5 14.0 sale 1.0
或者如果除第一个元素之外的所有元素都应该是 'sale',我们通过将 first
元素与 'install' 进行比较来创建一个逻辑变量 ('ind')连续元素为 'sale'(使用 lead
),然后是 filter
组,其中 all
和 'ind' 为真。如果需要,我们可以使用 select
.
df1 %>%
group_by(id) %>%
mutate(ind= first(event)=='install' & lead(event, default='sale')=='sale') %>%
filter(all(ind)) %>%
ungroup() %>%
select(-ind)
或者我们可以用data.table
.,按'id'分组,if
行数大于1(.N >1
),第一个元素是'install'(event[1L]=='install'
)和all
其余元素为'sale',则得到Data.table(.SD
).[=26的子集=]
library(data.table)
setDT(df1)[, if(.N > 1 & event[1L]=='install' & all(event[2:.N]=='sale')) .SD, by = id]
# id time event timediff
#1: 1 15.0 install NA
#2: 1 15.3 sale 0.3
#3: 1 16.0 sale 0.3
#4: 5 13.0 install NA
#5: 5 14.0 sale 1.0