不幸的是,stem 函数没有返回任何内容,这让生活变得困难。另外,代码是用 C 语言编写的,可以在here 获得。我尝试使用简单的 R 函数复制 stem 函数,这当然与 C 代码不匹配,但它适用于此示例数据集。我当然没有包含任何 stem 的论点(比例、宽度、原子)。
data(mtcars)
x <- mtcars$wt
stem(x) # you can see the result from the question.
mu = mean(x)
sdev <- sd(x)
y <- (1/(sdev * sqrt(2*pi))) * exp(-((x-mu)^2)/(2*sdev^2))
这是你的密度图:
par(mar=c(2,1,1,1))
plot(x, y, pch = 8, xaxt="n", yaxt="n", ylab="", col="grey)
现在我们需要从头开始重新发明stem 函数。我首先使用hist 函数定义“最佳”断点,我猜测类似于stem 所做的。
h <- hist(round(x,1), right=FALSE, plot=F)
bin <- h$breaks; bin
#[1] 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5
然后我使用 cut 将 x 值分配到正确的 bin 中。
xgr <- sort(cut(round(x,1), breaks = bin, right=FALSE, labels = FALSE, include = TRUE))
然后我使用 data.table 中的rowid 函数来定义 y 轴值,除以它的长度以获得密度,以便两个图使用相同的 y 轴系统。
library(data.table)
y <- rowid(xgr)/length(xgr); y
要绘制的实际字符 (pch) 来自小数点后的第一位。
pch <- as.character(round(10*(round(sort(x),1) %% 1))); pch
# [1] "5" "6" "8" "9" "1" "2" "3" "5" "6" "8" "8" "9" "1" "2" "2" "2"
#[17] "4" "4" "4" "4" "5" "5" "6" "6" "7" "8" "8" "8" "1" "2" "3" "4"
最后是 x 轴的“at”。
at <- seq(min(x), max(x), length.out=length(bin)-1)
x <- rep(at, h$counts)
points(x, y, pch = pch, col="red")
axis(side=1, at=at, labels=trunc(bin[-length(bin)]), tck=-0.02, mgp=c(1,0.3,0), col="red", col.axis="red")
一个显着的区别是stem 不像我在这里所做的那样使用round。它似乎在第 96 行和第 103 行使用了floor(x+0.5),这解释了细微的差异。另一个问题是它需要调整以使其更加健壮。
例如,将x 替换为mtcars$drat 需要将scale 参数更改为0.5。
x <- mtcars$drat
stem(x, scale=0.5)
The decimal point is at the |
2 | 889
3 | 0111112222
3 | 567778999999
4 | 111224
4 | 9