Изменить 2019-03-07, чтобы справиться с расширенным набором данных OP
Это можно решить путем агрегирования в неэквивалентном самосоединении
library(data.table)
# coerce character dates to IDate class
cols <- c("start", "end")
setDT(df)[, (cols) := lapply(.SD, as.IDate), .SDcols = cols]
# non-equi self-join and aggregate
tmp <- df[df, on = .(id, start <= end, end >= start), .N, by = .EACHI]
# append counts to original dataset
df[, overlapping.rows := tmp$N]
df
blockquote>id start end overlapping.rows 1: 174095 2018-12-19 2018-12-31 2 2: 227156 2018-12-19 2018-12-31 1 3: 210610 2018-04-13 2018-09-27 1 4: 27677 2018-04-12 2018-04-26 2 5: 370474 2017-07-13 2017-08-19 1 6: 303693 2017-02-20 2017-04-09 1 7: 74744 2016-10-03 2016-11-05 1 8: 174095 2018-12-01 2018-12-18 2 9: 27677 2018-03-01 2018-05-29 2 10: 111111 2018-01-01 2018-01-31 1 11: 111111 2018-11-11 2018-12-31 1 12: 174095 2018-11-30 2018-12-25 3
Используя data.table , связывающий код, можно написать более компактным, но и более запутанным способом:
[1122 ] Обратите внимание, что часть для добавления результатов к оригиналуlibrary(data.table) cols <- c("start", "end") setDT(df)[, (cols) := lapply(.SD, as.IDate), .SDcols = cols][ , overlapping.rows := df[df, on = .(id, start <= end, end >= start), .N, by = .EACHI]$N][]
df
основана на комментарии Фрэнка .
Моя первоначальная попытка использовать второе объединение для добавления результатов к исходному
df
потерпела неудачу в том случае, если есть разные значения для того жеid
, что и , указанного в OP . Это можно исправить, включив номер строки во второе объединение:library(data.table) # coerce character dates to IDate class cols <- c("start", "end") setDT(df)[, (cols) := lapply(.SD, as.IDate), .SDcols = cols] # append row number tmp <- df[, rn := .I][ # non-equi self-join and aggregate df, on = .(id, start <= end, end >= start), .(rn = i.rn, .N), by = .EACHI] # append counts to original dataset by joining on row number df[tmp, on = "rn", overlapping.rows := N][, rn := NULL] df
blockquote>id start end overlapping.rows 1: 174095 2018-12-19 2018-12-31 2 2: 227156 2018-12-19 2018-12-31 1 3: 210610 2018-04-13 2018-09-27 1 4: 27677 2018-04-12 2018-04-26 2 5: 370474 2017-07-13 2017-08-19 1 6: 303693 2017-02-20 2017-04-09 1 7: 74744 2016-10-03 2016-11-05 1 8: 174095 2018-12-01 2018-12-18 2 9: 27677 2018-03-01 2018-05-29 2 10: 111111 2018-01-01 2018-01-31 1 11: 111111 2018-11-11 2018-12-31 1 12: 174095 2018-11-30 2018-12-25 3
Объяснение
Условие соединения в соединении без равенства выполняет трюк. Два интервала не перекрываются , если первый заканчивается до начала второго или первый интервал начинается после окончания второго интервала,
e 1 < s 2 ИЛИ e 2 < s 1
Теперь, если два интервала действительно пересекаются / перекрываются, то противоположное из вышеприведенного должно быть истинным. Отрицая и применяя закон Де Моргана , мы получаем условия
s 2 = e 1 И e 2 ]> = s 1
, которые используются в неравных объединениях .
Данные
Расширенный набор данных OP, как описано в РЕДАКТИРОВАНИИ ОП 2019-03-06:
library(data.table) df <- fread("id start end 174095 2018-12-19 2018-12-31 227156 2018-12-19 2018-12-31 210610 2018-04-13 2018-09-27 27677 2018-04-12 2018-04-26 370474 2017-07-13 2017-08-19 303693 2017-02-20 2017-04-09 74744 2016-10-03 2016-11-05 174095 2018-12-01 2018-12-18 27677 2018-03-01 2018-05-29 111111 2018-01-01 2018-01-31 111111 2018-11-11 2018-12-31 174095 2018-11-30 2018-12-25")
Теперь я убежден, что это ошибка javac. Приведенные выше решения, которые добавляют универсальный параметр в InIterator, который либо скрывает, либо заменяет E, бесполезны, поскольку они не позволяют итератору делать что-то полезное, например, возвращать элемент типа E - E. Stuff's.
Однако это компилируется без Предупреждения (спасибо Jorn за подсказку):
public class Stuff<E> {
E bar;
Iterator<E> foo() {
class InIterator<Z> implements Iterator<E> {
@Override public boolean hasNext() { return false; }
@Override public E next() { return bar; }
@Override public void remove() { }
}
return new InIterator<Void>();
}
}
Определенно ошибка.
Хм, здесь нет предупреждений.
import java.util.Iterator;
public class Stuff<E> {
Iterator<E> foo() {
class InIterator implements Iterator<E> {
public boolean hasNext() {
return false;
}
public E next() {
return null;
}
public void remove() {
}
}
return new InIterator();
}
public static void main(String[] args) {
Iterator<String> i = new Stuff<String>().foo();
}
}
Я считаю, что происходит то, что вы игнорируете аргумент универсального типа, называя InIterator
без ссылки на универсальный в подписи (хотя он присутствует в интерфейсе).
Это относится к категории глупых предупреждений компилятора: вы написали класс так, что 100% экземпляров InIterator
будут реализовывать Iterator
, но компилятор не распознает это. (Я полагаю, это зависит от компилятора. Я не вижу предупреждения в моем компиляторе Eclipse, но я знаю, что компилятор Eclipse обрабатывает дженерики немного по-другому, чем компилятор JDK.)
Я утверждаю, что это менее понятно и менее близко к тому, что вы имеете в виду, но, возможно, более дружественно к компилятору и в конечном итоге эквивалентно:
public class Stuff<E> {
Iterator<E> foo() {
class InIterator<F> implements Iterator<F> {
@Override public boolean hasNext() { return false; }
@Override public E next() { return null; }
@Override public void remove() { }
}
return new InIterator<E>();
}
}
Yeah, I also agree that this should be a bug. If you "lift" the local class out of the method into a member class, it works fine too. And there isn't much difference between the two except different scoping and access to local variables.
public class Stuff<E> {
class InIterator implements Iterator<E> {
@Override public boolean hasNext() { return false; }
@Override public E next() { return null; }
@Override public void remove() { }
}
Iterator<E> foo() {
return new InIterator();
}
}