如何在R ggplot中制作此行列表的直方图?

8
我正在尝试通过以下步骤绘制第一行中的描述性变量。我还尝试过使用引用列/行名称,但没有成功。
  1. 旋转CSV数据中的行和列以获得线程A very simple histogram with R?所需的相应数据结构(高表)并使用ggplot绘制。
  2. 绘制事件的直方图作为Absolute变量XOR(AverageMinMax

    • 如果仅有绝对值,则只需在直方图中绘制绝对值。
    • 如果是(平均值、最小值和最大值),则在直方图中绘制它们与须(=whisker plot), 其中须的限制由最小值和最大值确定。

数据

  1. initially, data.csv

    "Vars"    , "Sleep", "Awake", "REM", "Deep"
    "Absolute",        ,       , 5     , 7
    "Average" , 7      , 12    ,       ,
    "Min"     , 4      , 5     ,       , 
    "Max"     , 10     , 15    ,       ,
    
  2. data after reshaping visually

                V1       V2       V3       V4
    Vars  Absolute Average  Min      Max     
    Sleep     <NA>        7        4       10
    Awake     <NA>       12        5       15
    REM          5     <NA>     <NA>     <NA>
    Deep         7     <NA>     <NA>     <NA>
    
  3. data after reshaping for R

     data <- structure(list(V1 = structure(c(3L, NA, NA, 1L, 2L), .Names = c("Vars", 
     "Sleep", "Awake", "REM", "Deep"), .Label = c(" 5", " 7", "Absolute"
     ), class = "factor"), V2 = structure(c(3L, 2L, 1L, NA, NA), .Names = c("Vars", 
     "Sleep", "Awake", "REM", "Deep"), .Label = c("12", " 7", "Average "
     ), class = "factor"), V3 = structure(c(3L, 1L, 2L, NA, NA), .Names = c("Vars", 
    "Sleep", "Awake", "REM", "Deep"), .Label = c(" 4", " 5", "Min     "
     ), class = "factor"), V4 = structure(c(3L, 1L, 2L, NA, NA), .Names = c("Vars", 
    "Sleep", "Awake", "REM", "Deep"), .Label = c("10", "15", "Max     "
     ), class = "factor")), .Names = c("V1", "V2", "V3", "V4"), row.names = c("Vars", 
    "Sleep", "Awake", "REM", "Deep"), class = "data.frame")
    

带有调试代码的R代码

dat.m <- read.csv("data.csv")

# rotate rows and columns
dat.m <- as.data.frame(t(dat.m)) # https://dev59.com/jGs05IYBdhLWcg3wQvyq#7342329 Comment 42-

library("reshape2")
dat.m <- melt(dat.m, id.vars="Vars")

## Just plot values existing there correspondingly    
library("ggplot2")
# https://stackoverflow.com/a/25584792/54964
# TODO following
#ggplot(dat.m, aes(x = "Vars", y = value,fill=variable)) 

错误
Error: id variables not found in data: Vars
Execution halted

R: 3.3.3,3.4.0(后移版本)
操作系统:Debian 8.7
使用sessionInfo()在加载这两个包后,重塑R reshape2,ggplot2等。

Platform: x86_64-pc-linux-gnu (64-bit)

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C   

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
[1] ggplot2_2.1.0  reshape2_1.4.2

loaded via a namespace (and not attached):
 [1] colorspace_1.3-2 scales_0.4.1     magrittr_1.5     plyr_1.8.4      
 [5] tools_3.3.3      gtable_0.2.0     Rcpp_0.12.10     stringi_1.1.5   
 [9] grid_3.3.3       stringr_1.2.0    munsell_0.4.3    

测试HaberdashPI的提案

图1中的输出中,SleepAwake中的绝对值错误。 如果是NA,则将值设置为零。

图1 HaberdashPI的提案输出不如预期。

enter image description here

dat.m在转置之前的数据结构

'data.frame':   4 obs. of  5 variables:
 $ Absolute: Factor w/ 2 levels " 5"," 7": NA NA 1 2
  ..- attr(*, "names")= chr  "Sleep" "Awake" "REM" "Deep"
 $ Average : Factor w/ 2 levels "12"," 7": 2 1 NA NA
  ..- attr(*, "names")= chr  "Sleep" "Awake" "REM" "Deep"
 $ Min     : Factor w/ 2 levels " 4"," 5": 1 2 NA NA
  ..- attr(*, "names")= chr  "Sleep" "Awake" "REM" "Deep"
 $ Max     : Factor w/ 2 levels "10","15": 1 2 NA NA
  ..- attr(*, "names")= chr  "Sleep" "Awake" "REM" "Deep"
 $ Vars    : chr  "Sleep" "Awake" "REM" "Deep"
      Absolute Average  Min      Max       Vars
Sleep     <NA>        7        4       10 Sleep
Awake     <NA>       12        5       15 Awake
REM          5     <NA>     <NA>     <NA>   REM
Deep         7     <NA>     <NA>     <NA>  Deep

转置后dat.m的数据结构

'data.frame':   16 obs. of  3 variables:
 $ Vars    : chr  "Sleep" "Awake" "REM" "Deep" ...
 $ variable: Factor w/ 4 levels "Absolute","Average ",..: 1 1 1 1 2 2 2 2 3 3 ...
 $ value   : chr  NA NA " 5" " 7" ...

    Vars variable value
1  Sleep Absolute  <NA>
2  Awake Absolute  <NA>
3    REM Absolute     5
4   Deep Absolute     7
5  Sleep Average      7
6  Awake Average     12
7    REM Average   <NA>
8   Deep Average   <NA>
9  Sleep Min          4
10 Awake Min          5
11   REM Min       <NA>
12  Deep Min       <NA>
13 Sleep Max         10
14 Awake Max         15
15   REM Max       <NA>
16  Deep Max       <NA>

测试 akash87 的 提案

代码

ds <- dat.m
str(ds)
ds
ds$variable
ds$variable %in% c("Min","Max")

错误输出是因为最后所有的False
 $ Vars    : chr  "Sleep" "Awake" "REM" "Deep" ...
 $ variable: Factor w/ 4 levels "Absolute","Average ",..: 1 1 1 1 2 2 2 2 3 3 ...
 $ value   : chr  NA NA " 5" " 7" ...
    Vars variable value
1  Sleep Absolute  <NA>
2  Awake Absolute  <NA>
3    REM Absolute     5
4   Deep Absolute     7
5  Sleep Average      7
6  Awake Average     12
7    REM Average   <NA>
8   Deep Average   <NA>
9  Sleep Min          4
10 Awake Min          5
11   REM Min       <NA>
12  Deep Min       <NA>
13 Sleep Max         10
14 Awake Max         15
15   REM Max       <NA>
16  Deep Max       <NA>
[1] "hello 3"
 [1] Absolute Absolute Absolute Absolute Average  Average  Average  Average 
 [9] Min      Min      Min      Min      Max      Max      Max      Max     
Levels: Absolute Average  Min      Max     
 [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
[13] FALSE FALSE FALSE FALSE

因为存在错误传递,所以执行 ds[ds$variable %in% c("Min","Max"), ] 将会得到 False 的输出。

测试Uwe的提案

使用明确的 data.table::dcast 代码和两次 data.table::melt。在 molten <- ... 之前打印出 sessionInfo()。请注意,因为错误来自于 molten <- ... 这一行,所以尚未加载 library(ggplot2)

$ Rscript test111.r 
    Vars "Average" "Max" "Min" Absolute
1: Sleep         7    10     4       NA
2: Awake        12    15     5       NA
3:   REM        NA    NA    NA        5
4:  Deep        NA    NA    NA        7
R version 3.4.0 (2017-04-21)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Debian GNU/Linux 8 (jessie)

Matrix products: default
BLAS: /usr/lib/openblas-base/libblas.so.3
LAPACK: /usr/lib/libopenblasp-r0.2.12.so

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

attached base packages:
[1] stats     graphics  grDevices utils     datasets  base     

other attached packages:
[1] data.table_1.10.4

loaded via a namespace (and not attached):
[1] compiler_3.4.0 methods_3.4.0 
Error in melt.data.table(transposed, measure.vars = c("Absolute", "Average")) : 
  One or more values in 'measure.vars' is invalid.
Calls: <Anonymous> -> melt.data.table
Execution halted

使用测试代码2测试Uwe的建议

代码

molten <- structure(list(Vars = structure(c(1L, 2L, 1L, 2L, 1L, 2L), class = "factor", .Label = c("V1", "V2")), variable = structure(c(1L, 1L, 2L, 2L, 3L, 3L), class = "factor", .Label = c("ave", "ave_max", "lepo")), value = c(7L, 8L, 10L, 10L, 4L, 4L)), .Names = c("Vars", "variable", "value"), row.names = c(NA, -6L), class = c("data.table", "data.frame"))

print(molten)

library(ggplot2)
ggplot(molten, aes(x = Vars, y = value, fill = variable, ymin = lepo, ymax = ave_max)) + 
  geom_col() + geom_errorbar(width = 0.2)

输出

  Vars variable value
1   V1      ave     7
2   V2      ave     8
3   V1  ave_max    10
4   V2  ave_max    10
5   V1     lepo     4
6   V2     lepo     4
Error in FUN(X[[i]], ...) : object 'lepo' not found
Calls: <Anonymous> ... by_layer -> f -> <Anonymous> -> f -> lapply -> FUN -> FUN
Execution halted

你能发布你期望的输出吗? - cirofdo
@TheBiro 我在正文中更仔细地定义了所需的输出。 - Léo Léopold Hertz 준영
我正在努力弄清楚我做错了什么,以便提供你所需要的解释。你期望得到什么? - akash87
@akash87 没有问题。我正在测试你的建议。到目前为止,这是最好的。 - Léo Léopold Hertz 준영
有哪些改进可以做呢? - akash87
5个回答

4
你的代码问题在于在ggplot aes函数中使用了带引号的"Vars"而不是简单的Vars。此外,数据集的标题混乱了。Absolute,Average等应该是数据集的列名,而不是值本身。这就是为什么你从melt函数得到错误的原因。
根据你的数据集,以下是我的尝试:
#Data
data = cbind.data.frame(c("Sleep", "Awake", "REM", "Deep"),
                        c(NA, NA, 5, 7),
                        c(7, 12, NA, NA),
                        c(4, 5, NA, NA),
                        c(10, 15, NA, NA))
colnames(data) = c("Vars", "Absolute", "Average", "Min", "Max")

#reshape
dat.m <- melt(data, id.vars="Vars")
#Stacked plot
ggplot(dat.m, aes(x = Vars, y = value)) + geom_bar(aes(fill=variable), stat = "identity")

这将产生:

stacked bar

#Or multiple bars
ggplot(dat.m, aes(x = Vars, y = value)) + 
  geom_bar(aes(fill=variable), stat = "identity", position="dodge") 

nonstacked

#Or separated by Vars
ggplot(dat.m, aes(x = Vars, y = value)) + geom_bar(aes(fill=variable), stat = "identity", position="dodge") + facet_wrap( ~ Vars, scales="free")

separatedbyvar

我正在为答案添加另一个图表。这与@Uwe的回答相协作。
#data
data <- structure(list(Vars = structure(1:2, class = "factor", .Label = c("V1", "V2")), ave = c(7L, 8L), ave_max = c(10L, 10L), lepo = c(4L, 4L)), .Names = c("Vars", "ave", "ave_max", "lepo"), row.names = c(NA, -2L), class = c("data.table", "data.frame"), sorted = "Vars")
#Melt
library(data.table)
mo = data.table::melt(data, measure.vars = c("ave"))
ggplot(mo, aes(x = Vars, y = value, fill = variable, ymin = lepo, ymax = ave_max)) + geom_col() + geom_errorbar(width = 0.2)

这将生成:

enter image description here


1
@LéoLéopoldHertz준영 我无法在这里添加图片,但很简单。只需将dat.m替换为molten即可在ggplot中使用。例如,ggplot(molten, aes(x = Vars, y = value)) + geom_bar(aes(fill=variable), stat = "identity", position="dodge")。 - user1480478
1
太好了,很高兴我能帮忙。 - user1480478
1
mo = data.table::melt(data, measure.vars = c("Absolute", "Average")) ggplot(mo, aes(Vars, value, fill = variable, ymin = Min, ymax = Max)) + geom_col() + geom_errorbar(width = 0.2) - user1480478
1
这是你想要的吗? mo = data.table::melt(data, measure.vars = c("ave")) ggplot(mo, aes(x = Vars, y = value, ymin = lepo, ymax = ave_max, fill = Vars)) + geom_col() + geom_errorbar(width = 0.2) - user1480478
1
在最后一个图中,我会添加 ggplot(mo, aes(x = Vars, y = value, fill = variable, ymin = lepo, ymax = ave_max)) + geom_col() + geom_errorbar(width = 0.2),因为这些值是关于平均值的。 - Léo Léopold Hertz 준영
显示剩余2条评论

3
您的基本问题是,当您调用dat.m <- as.data.frame(t(dat.m))时,您的列和行名称已经混乱了。这不是重新排列数据的正确方式。
您的术语有点令人困惑(您真正意思是直方图吗?),所以我不确定这是否是您想要的,但我认为要解决您所遇到的直接问题,您可以这样做:
library(ggplot2)
library(reshape2)

dat.m <- read.csv("data.csv")

m <- t(dat.m)
dat.m <- data.frame(m[2:nrow(m),])
names(dat.m) <- m[1,]
dat.m$Vars <- rownames(m)[2:nrow(m)]

dat.m <- melt(dat.m, id.vars="Vars")
ggplot(dat.m, aes(x = Vars, y = value,fill=variable)) + geom_bar(stat='identity')

这是我得到的输出:enter image description here 我所做的是手动重命名列名(names(data.m) <- etc...),并插入了一个名为Vars的新列,因为您需要这些名称作为dat.m的一列,而不是一组行名称,在melt中引用它们(这就是为什么您会遇到关于找不到Vars的错误)。这不太优雅,但它能完成工作。
看起来你做了比你实际需要做的工作还要多。似乎你已经在其他程序(Excel?)中收集了数据的汇总信息,这让我想到如果你只是将原始数据加载到R中并在R中计算平均值、最小值等,或者在那个外部程序中以更符合R规范的格式总结数据,那么你的问题可能有更简单的解决方案。由于我不知道原始数据的确切样子,所以无法给出更好的答案。
ggplot的很多内容都是围绕着一组关于如何组织数据的原则组织的:我建议阅读这篇关于dplyr的博客文章这篇关于tidyr的文章

1
嗯...我得到了不同的输出。你想要什么样的输出?你能画出来吗?我展示的内容使用了我向你展示的完全相同的代码,其中包含一个名为data.csv的文件,其内容与你的问题中复制的完全相同。 - HaberdashPI
我不确定你在评论中的意思。代码应该能够工作,无论原始数据大小如何(至少有两行,因为第一行是列名,因为t会破坏数据框格式的方式)。你所说的错误检查是什么意思?你能够重现我的输出吗? - HaberdashPI
我无法重现你的输出。您能否展示一下转置前后使用的数据结构呢? - Léo Léopold Hertz 준영

3
这是使用 data.table 的非常简洁的版本:
library(data.table)

# read data and transpose
transposed <- data.table::dcast(data.table::melt(fread("data2.csv"), id.vars = "Vars"), 
                                variable ~ ...)
setnames(transposed, "variable", "Vars")
# reshape to long for plotting
molten <- data.table::melt(transposed, measure.vars = c("Absolute", "Average"))

编辑:我已修改上述代码,使用双冒号运算符明确指定melt()dcast()应该采用的命名空间。通常情况下这不是必需的,因为data.table已经被加载。然而,OP报告了可能由于在data.table之后加载了reshape2包而导致的问题。data.table包具有自己更快的实现reshape2::dcast()reshape2::melt() 。当两个包都被加载时,可能会出现名称冲突。

library(ggplot2)
ggplot(molten, aes(Vars, value, fill = variable, ymin = Min, ymax = Max)) + 
  geom_col() + geom_errorbar(width = 0.2)

数据

我需要从csv文件中删除 "。这是最快的方法,以消除来自 fread() 的错误消息,该消息抱怨标题的格式。所以,data2.csv 看起来像:

enter image description here

Vars    ,   Sleep,  Awake,    REM, Deep 
Absolute,        ,       , 5     , 7
Average , 7      , 12    ,       , 
Min     , 4      , 5     ,       , 
Max     , 10     , 15    ,       , 

1
请尝试更新代码。你的环境似乎有些混乱。对我来说,这段代码是正常工作的。也许你需要用一个干净的 R 会话重新启动一下? - Uwe
1
感谢您提供sessionInfo()的输出。正如我编辑后的答案所怀疑的,您已经加载了reshape2,这可能会导致问题。因此,要么尝试我的编辑代码(它显式地调用melt()dcast()data.table版本),要么避免加载reshape2 - Uwe
请展示输入文件 test111.csv 的内容。 - Uwe
1
我相信,我解决了这个谜题:这是由于数据中的 " 导致的。作为一种解决方法,请从输入文件中删除它们,然后再次测试。我稍后将适当地更新我的答案中的代码。 - Uwe
让我们在聊天室中继续这个讨论 - Uwe

2
我会采用不同的方法来处理这个问题。如果我将原始数据作为

参数传递给函数,然后在函数内部对其进行操作和更改,最终返回一个新的修改后的数据。

> data
  Vars variable value
 Sleep Absolute  <NA>
 Awake Absolute  <NA>
   REM Absolute     5
  Deep Absolute     7
 Sleep  Average     7
 Awake  Average    12
   REM  Average  <NA>
  Deep  Average  <NA>
 Sleep      Min     4
 Awake      Min     5
   REM      Min  <NA>
  Deep      Min  <NA>
 Sleep      Max    10
 Awake      Max    15
   REM      Max  <NA>
  Deep      Max  <NA>

将数据转换为:
minmax <- ds[ds$variable %in% c("Min","Max"), ]
absol  <- ds[ds$variable %in% c("Average", "Absolute"), ]
minm   <- dcast(minmax, Vars ~ variable)
absol <- merge(absol, minm, by = "Vars", all.x = T)
>absol

      Vars variable value Max Min
     Awake  Average    12  15   5
      Deep Absolute     7  NA  NA
       REM Absolute     5  NA  NA
     Sleep  Average     7  10   4

然后我可以使用ggplot2,然后我就能使用。
ggplot(absol, aes(x = Vars, y = value, fill = variable)) +
       geom_bar(stat = "identity") +
       geom_errorbar(aes(ymin = Min, ymax = Max), width = .25)

这导致:

enter image description here


我在这里添加了一个维基答案,明确展示了数据转换的答案:https://dev59.com/fqHia4cB1Zd3GeqPZdPA#44097150 - Léo Léopold Hertz 준영
1
我必须问为什么?数据应该是什么样子的?为什么会有间隙?在这个问题中解释的间隙似乎更多地涉及数据类型,而不是完全随机缺失。 - akash87
我在思考如何在这里使用 dat.m <- melt(as.data.table(dat.m, keep.rownames = "Vars"), id.vars = "Vars") # https://stackoverflow.com/a/44128640/54964,而不是手动转换成长表格。你觉得呢?我认为这一行代码也可以在这里非常有用。 - Léo Léopold Hertz 준영
肯定可以。而且它会增加效率。 - akash87

-1

完成 akash87 的代码,因为在他的答案中数据转换不是从原始数据集显式进行的。

library("ggplot2")

dat.m <- read.csv("data.csv", strip.white=TRUE)

m <- t(dat.m)
dat.m <- data.frame(m[2:nrow(m),])
names(dat.m) <- m[1,]
dat.m$Vars <- rownames(m)[2:nrow(m)]

library("reshape2")
dat.m <- melt(dat.m, id.vars="Vars")

ds <- dat.m
# https://dev59.com/fqHia4cB1Zd3GeqPZdPA#44090815
minmax <- ds[ds$variable %in% c("Min","Max"), ]
absol  <- ds[ds$variable %in% c("Average", "Absolute"), ]
minm   <- dcast(minmax, Vars ~ variable)
absol <- merge(absol, minm, by = "Vars", all.x = T)

absol

ggplot(absol, aes(x = Vars, y = value, fill = variable)) +
       geom_bar(stat = "identity") +
       geom_errorbar(aes(ymin = Min, ymax = Max), width = .25)

输出:与akash87的答案相同。


我认为在转换为长表时,应该也在这里应用以下答案的方法:https://stackoverflow.com/a/44128640/54964 - Léo Léopold Hertz 준영

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接