【问题标题】:Split a dataset into two dataframes using multiple columns in R使用 R 中的多列将数据集拆分为两个数据框
【发布时间】:2015-10-12 21:42:12
【问题描述】:

假设我的数据集如下所示:

working_data <- dplyr::data_frame("Date" = c("2015-01-01", "2015-01-01", "2015-01-02", "2015-01-03", "2015-01-04", "2015-01-04", "2015-01-04"),
                                  "Time" = c("15:01", "15:01", "21:04", "13:19", "07:15", "07:15", "07:15"),
                                  "SeizureTime" = c("0:10", "0:07", "0:11", "0:04", "0:08", "0:06", "0:07"),
                                  "ET" = c("0:35", "0:35", "0:04", "1:10", "3:35", "3:35", "3:35"),
                                  "ONumber" = c("(123)555-1234", "(123)555-1234", "(123)555-9999", "(000)555-9876", "(123)555-1111", "(123)555-1111", "(123)555-1111"),
                                  "TNumber" = c("(123)555-1234", "(123)555-1234", "(123)555-9999", "(000)555-9876", "(123)555-1111", "(123)555-1111", "(123)555-1111"),
                                  "CT" = c("a", "a", "b", "a", "b", "b", "b"))

我想从这些数据中提取可能重复的行。我这样做的方法如下:

while (nrow(working_data) != 0) {
          target_call <- working_data[1, ]
          working_data <- working_data[-1, ]
          similar_calls <- working_data %>% dplyr::filter(Date == target_call$Date,
                                                   Time == target_call$Time,
                                                   ET == target_call$ET,
                                                   ONumber == target_call$ONumber,
                                                   TNumber == target_call$TNumber)

第一个循环将设置target_call 等于working_data 的第一行,并将设置similar_calls 等于第二行。假设一切顺利......我遇到的问题是,一旦我在target_callsimilar_calls 上运行我的函数,我就不想再看到它们了。所以我想从working_data 中删除被拉入similar_calls 的数据。

填充target_callsimilar_calls 后,我需要确定哪些调用(如果有)与target_call 相同,然后进一步确定哪个是正确的选择,一旦我'选择了正确的调用,将其添加到名为 resolved_calls 的新数据集。如果similar_calls 中还有剩余呼叫,那么我需要重复选择呼叫的分析并将其中一个呼叫添加到resolved_calls

我能想到的最佳方法是将数据拆分为两个单独的数据帧。但是当我处理多个列时,我不知道该怎么做。我唯一的选择是一个非常丑陋的 ifelse 语句,例如:

working_data$Group <- ifelse(working_data$Date == target_call$Date & ... & working_data$TNumber == target_call$TNumber, 1, 0)
similar_calls <- working_data %>% dplyr::filter(Group == 1)
working_data <- working_data %>% dplyr::filter(Group == 0)

有没有更好的方法来做到这一点?

【问题讨论】:

    标签: r split dataframe dplyr


    【解决方案1】:

    您还没有真正描述您想对每个组做什么,但让我们假设您只想获取每组相似调用中的第一个元素。然后像duplicated 函数这样的东西可以很好地工作:

    working_data[with(working_data, !duplicated(paste(Date, Time, ET, ONumber, TNumber))),]
    # Source: local data frame [4 x 7]
    # 
    #         Date  Time SeizureTime    ET       ONumber       TNumber    CT
    #        (chr) (chr)       (chr) (chr)         (chr)         (chr) (chr)
    # 1 2015-01-01 15:01        0:10  0:35 (123)555-1234 (123)555-1234     a
    # 2 2015-01-02 21:04        0:11  0:04 (123)555-9999 (123)555-9999     b
    # 3 2015-01-03 13:19        0:04  1:10 (000)555-9876 (000)555-9876     a
    # 4 2015-01-04 07:15        0:08  3:35 (123)555-1111 (123)555-1111     b
    

    在 dplyr 语法中,您可以使用 group_by 按适当的元素进行分组,然后您可以使用 filterrow_number 来获取每个组中的第一个实例:

    working_data %>%
      group_by(Date, Time, ET, ONumber, TNumber) %>%
      filter(row_number() == 1)
    # Source: local data frame [4 x 7]
    # Groups: Date, Time, ET, ONumber, TNumber [4]
    # 
    #         Date  Time SeizureTime    ET       ONumber       TNumber    CT
    #        (chr) (chr)       (chr) (chr)         (chr)         (chr) (chr)
    # 1 2015-01-01 15:01        0:10  0:35 (123)555-1234 (123)555-1234     a
    # 2 2015-01-02 21:04        0:11  0:04 (123)555-9999 (123)555-9999     b
    # 3 2015-01-03 13:19        0:04  1:10 (000)555-9876 (000)555-9876     a
    # 4 2015-01-04 07:15        0:08  3:35 (123)555-1111 (123)555-1111     b
    

    如果您想更一般地处理组,您可以使用group_by 然后summarize 以不同方式总结组:

    # Take text data in format mm:ss and return the number of seconds
    secs <- function(x) {
      spl <- strsplit(x, ":")
      60*as.numeric(sapply(spl, "[", 1)) + as.numeric(sapply(spl, "[", 2))
    }
    working_data %>%
      group_by(Date, Time, ET, ONumber, TNumber) %>% 
      summarize(meanSeizure=mean(secs(SeizureTime)))
    # Source: local data frame [4 x 6]
    # Groups: Date, Time, ET, ONumber [?]
    # 
    #         Date  Time    ET       ONumber       TNumber meanSeizure
    #        (chr) (chr) (chr)         (chr)         (chr)       (dbl)
    # 1 2015-01-01 15:01  0:35 (123)555-1234 (123)555-1234         8.5
    # 2 2015-01-02 21:04  0:04 (123)555-9999 (123)555-9999        11.0
    # 3 2015-01-03 13:19  1:10 (000)555-9876 (000)555-9876         4.0
    # 4 2015-01-04 07:15  3:35 (123)555-1111 (123)555-1111         7.0
    

    【讨论】:

    • 这是一个经过深思熟虑的回应,我很感激。直到您的回答,我才意识到表明需要对数据执行什么操作对于我如何拆分数据很重要。我会修改问题以反映这一点。
    猜你喜欢
    • 2020-09-22
    • 2017-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多