【问题标题】:Filtering a dataset after grepl in R?在R中的grepl之后过滤数据集?
【发布时间】:2016-06-20 10:37:34
【问题描述】:

我有以下数据集:

USERNAME API_TRACK_EVENT         TIME
userA    Viewed pic              1454941960
userA    Order/payment           1454941972
userA    Order/Changed Address   1454941976
userB    Viewed pic              1454941983
userB    Order/guestlogin        1454941986
userB    Order/Changed Address   1454941992

我只想接受较早的“订单”,即用户 A 的“订单/付款”和用户 B 的“订单/访客登录”。

话虽如此,所有其他无序事件应该保持不变。

因此,输出数据集将是:

USERNAME API_TRACK_EVENT         TIME
userA    Viewed pic              1454941960
userA    Order/payment           1454941972
userB    Viewed pic              1454941983
userB    Order/guestlogin        1454941986

那么,我该怎么做呢? [也开放使用 dplyr。]

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    这是一个带有基本 R 的选项:

    0) 根据 USERNAME 和 TIME 对数据进行排序:

    df <- df[order(df$USERNAME, df$TIME),]
    

    a) 检查行是否包含订单信息:

    idx <- grepl("Order", df$API_TRACK_EVENT, ignore.case = TRUE)
    

    b) USERNAME 组的子集

    subset(df, ave(idx, USERNAME, FUN = cumsum) <= 1L | !idx)
    
    #  USERNAME  API_TRACK_EVENT       TIME
    #1    userA       Viewed_pic 1454941960
    #2    userA    Order/payment 1454941972
    #4    userB       Viewed_pic 1454941983
    #5    userB Order/guestlogin 1454941986
    

    这仅包含第一个订单行和任何其他行(没有订单信息)。

    【讨论】:

    • 对不起,我错过了行需要按顺序排列的细节。到time,最早的应该存在于结果数据集中。感谢您对另一个答案的评论,我被提醒了这个错误:)
    • @Dawny33,我添加了一个步骤来订购数据
    • 感谢您提供如此详细的答案。 :)
    【解决方案2】:

    我们可以使用slice/which.max/grep 过滤掉dplyr 中的行。按'USERNAME'分组后,得到grepl的逻辑索引,用which.max包裹得到第一个TRUE值的数字索引,使用seq1:indexslice获取序列它对行进行子集化。此方法假定“订单”元素出现在每个“用户名”的末尾,如示例所示。

    library(dplyr)
    df1 %>%
        arrange(USERNAME, TIME) %>%
        group_by(USERNAME) %>%
        slice(seq(which.max(grepl("Order", API_TRACK_EVENT))))
    #  USERNAME  API_TRACK_EVENT       TIME
    #     <chr>            <chr>      <int>
    #1    userA       Viewed pic 1454941960
    #2    userA    Order/payment 1454941972
    #3    userB       Viewed pic 1454941983
    #4    userB Order/guestlogin 1454941986
    

    但是,如果“Order”元素没有排序,我们可以使用duplicatedgrepl 来保留包含任何没有“Order”元素或只有第一个“Order”元素的行。

    df1 %>%
        arrange(USERNAME, TIME) %>%
        group_by(USERNAME) %>%
        filter( {idx =  grepl("^Order", API_TRACK_EVENT);
                !duplicated(idx)|!idx})
    
    #  USERNAME  API_TRACK_EVENT       TIME
    #     <chr>            <chr>      <int>
    #1    userA       Viewed pic 1454941960
    #2    userA    Order/payment 1454941972
    #3    userB       Viewed pic 1454941983
    #4    userB Order/guestlogin 1454941986
    

    注意:编辑来自@docendodiscimus 的贡献


    或者使用data.table的第一种方法

    library(data.table)
    setDT(df1)[df1[order(USERNAME, TIME), .I[seq(which.max(grepl("Order", 
                           API_TRACK_EVENT)))], USERNAME]$V1]
    

    【讨论】:

    • 可以解释最后一行吗? slice(seq(which.max(grep("Order", API_TRACK_EVENT))))
    • @akrun (+1)感谢您的回答。如果需要按时间订购,又想拿most early一个,可以怎么改?很抱歉错过了 qn 中的详细信息 :)
    • @docendodiscimus 感谢您的评论。我忘了{}
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-22
    • 2015-11-03
    • 1970-01-01
    相关资源
    最近更新 更多