Прокручивать строки и подсчитывать количество строк, соответствующих нескольким критериям в R - PullRequest
1 голос
/ 09 мая 2019

У меня есть набор данных, который выглядит следующим образом:

        city period_day       date 
1  barcelona    morning 2017-01-15         
2  sao_paulo  afternoon 2016-12-07         
3  sao_paulo    morning 2016-11-16         
4  barcelona    morning 2016-11-06         
5  barcelona  afternoon 2016-12-31         
6  sao_paulo  afternoon 2016-11-30         
7  barcelona    morning 2016-10-15         
8  barcelona  afternoon 2016-11-30         
9  sao_paulo  afternoon 2016-12-24         
10 sao_paulo  afternoon 2017-02-02         

Для каждой строки я хочу подсчитать, сколько строк имеют более старую дату, чем дата строки, как для города, так и для period_day.В данном случае я хочу получить такой результат:

        city period_day       date row_count
1  barcelona    morning 2017-01-15         2
2  sao_paulo  afternoon 2016-12-07         1
3  sao_paulo    morning 2016-11-16         0
4  barcelona    morning 2016-11-06         1
5  barcelona  afternoon 2016-12-31         1
6  sao_paulo  afternoon 2016-11-30         0
7  barcelona    morning 2016-10-15         0
8  barcelona  afternoon 2016-11-30         0
9  sao_paulo  afternoon 2016-12-24         2
10 sao_paulo  afternoon 2017-02-02         3

Когда row_count равен 0, это означает, что это более старая дата.

Я нашел решение, но это заняло слишком много временис большим количеством данных.Вот код:

get_count_function <- function(df) {
  idx <- 1:nrow(df)

  count <- sapply(idx, function(x) {
    name_city <-
      df %>% select(city) %>% filter(row_number() == x) %>% pull()
    name_period <-
      df %>% select(period_day) %>% filter(row_number() == x) %>% pull()

    date_row <- df %>%
      select(date) %>%
      filter(row_number() == x) %>%
      pull()

    date_any_row <- df %>%
      filter(dplyr::row_number() != x,
             city == name_city,
             period_day == name_period) %>%
      select(date) %>%
      pull()

    how_many <- sum(date_row > date_any_row)

    return(how_many)

  })

  return(count)

}

Как мне сделать эту функцию более эффективной?

Ответы [ 2 ]

1 голос
/ 09 мая 2019

Это должно работать, если вы хотите использовать пакет data.table:

library(data.table)

dat <- read.table(header=T, row.names=1, text="
        city period_day       date 
1  barcelona    morning 2017-01-15         
2  sao_paulo  afternoon 2016-12-07         
3  sao_paulo    morning 2016-11-16         
4  barcelona    morning 2016-11-06         
5  barcelona  afternoon 2016-12-31         
6  sao_paulo  afternoon 2016-11-30         
7  barcelona    morning 2016-10-15         
8  barcelona  afternoon 2016-11-30         
9  sao_paulo  afternoon 2016-12-24         
10 sao_paulo  afternoon 2017-02-02   
")

dat <- as.data.table(dat)

dat[, row_count := (order(as.Date(date)) - 1), by=.(city, period_day)]

# Check
dat

##          city period_day       date row_count
##  1: barcelona    morning 2017-01-15         2
##  2: sao_paulo  afternoon 2016-12-07         1
##  3: sao_paulo    morning 2016-11-16         0
##  4: barcelona    morning 2016-11-06         1
##  5: barcelona  afternoon 2016-12-31         1
##  6: sao_paulo  afternoon 2016-11-30         0
##  7: barcelona    morning 2016-10-15         0
##  8: barcelona  afternoon 2016-11-30         0
##  9: sao_paulo  afternoon 2016-12-24         2
## 10: sao_paulo  afternoon 2017-02-02         3
1 голос
/ 09 мая 2019

Попробуйте это:

library(tidyverse)

dat %>%
  group_by(city, period_day) %>%
  mutate(row_count = order(date) - 1) %>%
  ungroup()

При вызове order он возвращает индексы, указывающие на порядок значения в выбранной группе значений (date),Вычитая 1 из индексов, вы получаете count значений , предшествующих текущему значению, в определенной группе.Например, если это мин.значение в группе, оно имеет индекс 1, поэтому ему ничего не предшествует (1 - 1 = 0), если индекс 2 - ему предшествует только одно значение (одно старшее date перед ним) и т. д.

Данные:

dat <- read.table(
  text = "        city period_day       date
  barcelona    morning 2017-01-15
  sao_paulo  afternoon 2016-12-07
  sao_paulo    morning 2016-11-16
  barcelona    morning 2016-11-06
  barcelona  afternoon 2016-12-31
  sao_paulo  afternoon 2016-11-30
  barcelona    morning 2016-10-15
  barcelona  afternoon 2016-11-30
  sao_paulo  afternoon 2016-12-24
  sao_paulo  afternoon 2017-02-02",
  header = T,
  colClasses = c("character", "character", "Date")
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...