Это довольно интересно - спасибо за ваш вопрос. Здесь виноваты не ваш код и подход к вашему графику, а способ, которым position_jitter()
применяется к набору данных. Объект, созданный из position_jitter()
, в основном можно рассматривать как массив значений джиттера, который применяется к вашему набору данных построчно. Имейте в виду, я не точно уверен, что это действительно то, что происходит, но поведение соответствует такому способу работы.
Определение проблемы
Итак, что здесь происходит? Что ж, сначала позвольте мне создать фиктивный набор данных для использования в качестве примера.
set.seed(1234)
df <- data.frame(x=1:10, y=rnorm(10))
Я построю набор данных и применю предварительно созданный объект position_jitter()
к geom_point()
и geom_text_repel()
. Вы увидите, что на выходном графике все сегменты совпадают с точками, как и следовало ожидать.
pos <- position_jitter(width=0.5, seed=1)
ggplot(df, aes(x,y)) + geom_point(position=pos) +
geom_text_repel(aes(label=x), color='red', position=pos, force=20)
Проблемы становятся очевидными, если мы применяем geom_point()
ко всему набору данных, но применяем geom_text_repel()
к подмножеству этого набора данных (что в основном является вашим собственным случаем).
df_rep <- df %>% dplyr::filter(x > 5)
ggplot(df, aes(x,y)) + geom_point(position=pos) +
geom_text_repel(data=df_rep, aes(label=x), color='red', position=pos, force=20)
Теперь сегменты не выстраиваются в линию, что вы и наблюдаете. Ключевым моментом здесь является понимание того, что pos
вообще не связано с наборами данных, используемыми для построения графиков. Если вы думаете об этом как о числовом векторе, который умножается на эстетику x перед построением графика, поведение имеет смысл. Первое наблюдение в полном наборе данных корректируется на то же значение, что и первый набор в подмножестве, но это означает, что определенные наблюдения не колеблются одинаково, если только они не находятся в одной и той же последовательности в обоих наборах данных.< /em> Мы можем проверить гипотезу о том, как работает pos
, создав набор данных, состоящий из первых нескольких строк из df
и последних нескольких строк из df
. Если наша гипотеза верна, то первые несколько строк должны быть в порядке, но дрожание для последних нескольких строк будет другим. Давайте проверим это:
df_rep2 <- df[c(1:3, 8:10),] # choosing first few and last few obs in df
ggplot(df, aes(x,y)) + geom_point(position=pos) +
geom_text_repel(data=df_rep2, aes(label=x), color='red', position=pos, force=20)
Теперь должно быть совершенно очевидно, почему линии расположены не так, как точки в вашем примере.
Как решить проблему
Так что исправить? Итак, мы знаем, что pos
нужно применять в той же последовательности к объектам geom_point()
и geom_text_repel()
. Я бы хотел, чтобы был более элегантный способ сделать это (и, возможно, он есть), но вы можете избежать этого, используя два отдельных вызова geom_point()
: один соответствует набору данных, используемому для geom_text_repel()
, а другой — «всему остальному».
По крайней мере, есть хороший способ определить «все остальное» — использовать anti_join()
из dplyr
. Вот исправление:
df_not <- anti_join(df, df_rep) # find everything in df that is not df_rep
ggplot(df, aes(x,y)) +
geom_point(data=df_not, position=pos) +
geom_point(data=df_rep, position=pos) +
geom_text_repel(data=df[which(df$x>5),], aes(label=x), color='red', position=pos, force=20)
person
chemdork123
schedule
09.06.2020
Pop1=="bla" | Pop1=="ME" | Pop1=="Nafr" | Pop1=="Is"
- этоPop1 %in% c("bla", "ME", "Nafr", "Is")
- person Gregor Thomas   schedule 09.06.2020