如何绘制一个茎叶图,显示真正的叶子没有四舍五入

时间:2016-09-03 16:43:54

标签: r plot

例如,我有数字:43.2, 45.3, 48.1, 54.2。当我使用stem()函数绘制一个图时,我得到了:stem()函数显示如下

x <- c(43.2, 45.3, 48.1, 54.2)

stem(x)
# 
# The decimal point is 1 digit(s) to the right of the |
#   
#   4 | 3
#   4 | 58
#   5 | 4

但是从情节来看,我只知道数字是:43,45,48,54。所以我想要一个函数绘制一个茎叶图,我仍然可以知道确切的数字而不用向上舍入。

此外,我希望它只使用一个数字来表示词干,同时在叶子中显示else。例如,43.2应该是一个词干4而一个词3.243.22应该是一个词干4和一个词3.22。 对于数字:43.2, 45.3, 48.1, 54.2。我想要这样的情节:

enter image description here

2 个答案:

答案 0 :(得分:4)

x <- c(43.2, 45.3, 48.1, 54.2)

stem(x)
# 
# The decimal point is 1 digit(s) to the right of the |
#   
#   4 | 3
#   4 | 58
#   5 | 4

stem2(x)
# 
# The decimal point is 1 digit(s) to the right of the |
#   
#   4 | 3.2
#   4 | 5.3, 8.1
#   5 | 4.2

stem2 <- function(x) {
  cx <- gsub('^.', ', ', as.character(sort(x)))
  co <- capture.output(stem(x))
  m <- gregexpr('\\d(?!.*\\|)', co, perl = TRUE)
  l <- regmatches(co, m)
  l <- t(do.call('rbind', lapply(l, `length<-`, max(lengths(l)))))
  l[!is.na(l)] <- cx
  regmatches(co, m) <- data.frame(l)
  cat(gsub(' , ', ' ', co), sep = '\n')
}

答案 1 :(得分:1)

这是一种方式。我已使用下面的data.table包,所以如果您没有,请先安装它。如果您真的希望使用常规数据框创建绘图,请告诉我,我会相应地调整它。

library(data.table) # Install via install.packages(data.table)

# x is the vector of numbers for which you want to create the stem and leaf plot
# leftDigits gives the position of the '|' relative to the decimal point, 
# e.g. leftDigits = 0 will result in 43.2 being represented as 43 | 0.2
# e.g. leftDigits = 1 will result in 43.2 being represented as 4 | 3.2
# I have included a rounding parameter, due to floating point problems seen when taking the difference of two numbers
# rounding = 2 means that your numbers will show to 2 decimal places. Change as desired.
myStem <- function(x, leftDigits, rounding = 2){
  data = data.table("x" = x) # Create a data.table
  data[, left := floor(x/10^leftDigits)] # Get the number that will be to the left of '|'
  data[, right := round(x - left*10^leftDigits, rounding)] # The remainder will be on the right
  data = data[, paste(sort(right), collapse = ", "), by = left] # For each 'left', Place all the 'right' values in a comma separated string.
  data[, out := paste(left, " | ", V1), by = left] # Add the "|"
  cat(data$out, sep = "\n") # Output
}

# Example
myStem(x = c(43.2, 45.3, 48.1, 54.2), 1)
# 4  |  3.2, 5.3, 8.1
# 5  |  4.2

编辑:如果您想要背靠背图,那么以下代码应该可以使用。它的工作方式与前面的代码类似

myStem <- function(leftVals, rightVals, mainDigits, rounding = 10){
  data = data.table("x" = leftVals, "ind" = "x") 
  data = rbind(data, data.table("x" = rightVals, "ind" = "y")) 
  data[, main := floor(x/10^mainDigits)] 
  data[, right := round(x - main*10^mainDigits, rounding)] 
  data = data[, ifelse(ind == "x", paste0(-sort(-right), collapse = ", "), paste0(sort(right), collapse = ", ")), by = c("ind", "main")] # For each 'main', Place all the 'right' values in a comma separated string.
  data = dcast(data, main ~ ind, value.var = "V1")
  data[, "left|" := ifelse(is.na(x), "", "|")]
  data[, "right|" := ifelse(is.na(y), "", "|")]
  data[, x := ifelse(is.na(x), "", x)]
  data[, y := ifelse(is.na(y), "", y)]
  data = data[, c("x", "left|", "main", "right|", "y"), with = F]
  maxLengthY = max(nchar(data$y))
  data[, y := unlist(lapply(y, function(z) paste0(z, paste0(replicate(maxLengthY - nchar(z), " "), collapse = ""))))]
  colnames(data) = rep(" ", ncol(data))
  data
}

# Example
myStem(leftVals = c(43.2, 45.3, 48.1, 54.2), rightVals = c(30.2, 34.5, 44.3), 1)

1:                 3 | 0.2, 4.5
2: 8.1, 5.3, 3.2 | 4 | 4.3     
3:           4.2 | 5