R语言 如何制作类似于论文“把我从你的F******邮件列表中删除”的散点图?

e5nszbig  于 2022-12-20  发布在  其他
关注(0)|答案(3)|浏览(154)
  • 这是一个严肃的问题,请不要把它当作玩笑 *

这张散点图来自一篇声名狼借的同名论文,Mazières和Kohle(2005)发表在一本掠夺性杂志上,有些人可能知道它。

我对重新创建相同的散点图来测试一个新的 * 基于密度的聚类算法 * 非常感兴趣,而不需要从头开始创建所有的字母。
是否有任何方法可以简化此过程?(例如,数据集、软件包或重新创建绘图的智能方法)

gg58donl

gg58donl1#

既然网格包支持剪切路径,我们可以:

library(grid)
library(ggplot2)

tg <- textGrob("Get me off\nYour Fuck\ning Mailing\nList", x = 0.2,
               hjust = 0,
               gp = gpar(cex = 6, col = "grey", font = 2))
cg <- pointsGrob(x= runif(15000), y = runif(15000), pch = 3,
                 gp = gpar(cex = 0.5))

rg <- rectGrob(width = unit(0.5, 'npc'), height = unit(0.1, 'npc'),
               gp = gpar(fill = 'red'))

ggplot(data = NULL, aes(x = 100, y = 100)) +
  geom_point(col = 'white') +
  theme_classic() +
  theme(panel.border = element_rect(fill = 'white', linewidth = 1))

pushViewport(viewport(clip = tg))
grid.draw(cg)

eqoofvh9

eqoofvh92#

如果你想真正生成文本中的随机点,你可以使用Python的Numpy和Pillow模块相对容易地完成。

import numpy as np
import matplotlib.pyplot as plt
from PIL import Image, ImageDraw, ImageFont

lines = ["Get me off", "your Fuck", "ing Mailing", "List"]

# get a nice heavy font
font = ImageFont.truetype("fonts/Lato-Black.ttf", size=200)

# calculate width
width = max(font.getbbox(line)[2] for line in lines)

# create BW image containing text
im = Image.new('1', (width, len(lines) * font.size))
draw = ImageDraw.Draw(im)
for i, line in enumerate(lines):
    draw.text((0, i * font.size), line, font=font, fill=1)

# sample points
y, x = np.where(np.array(im) > 0)
ii = np.random.randint(len(x), size=sum(map(len, lines)) * 50)
x = x[ii] / im.width
y = y[ii] / im.height

# recreate figure
fig, ax = plt.subplots()
ax.semilogy()
ax.scatter(x, 10**(y*-5), 7**2, linewidths=0.5, marker='+', color='black')
ax.set_xlabel("Your Fucking Mailing List")
ax.set_ylabel("Get me off")
ax.set_title("Get me off Your Fucking Mailing List")

这可能会产生如下结果:

由于没有屏蔽,因此很难看到字母,但考虑到您似乎想要用于聚类的点,这可能不是很重要。

u7up0aaq

u7up0aaq3#

使用matplotlib和裁剪,这并不容易处理多行(不幸的是):

import matplotlib.pyplot as plt
from matplotlib.textpath import TextPath
from matplotlib.font_manager import FontProperties
from matplotlib.transforms import IdentityTransform

import numpy as np

ax = plt.subplot()

N = 7000
x = np.random.random(size=N)
y = np.random.random(size=N)

ax.scatter(x, y, marker='+', color='k', lw=0.5)
text = 'StackOverflow'

text = TextPath((60, 200), text,
                prop=FontProperties(weight='bold', size=55),
                )

ax.collections[0].set_clip_path(text, transform=IdentityTransform())

输出:

相关问题