【问题标题】:Restructuring a data frame for 3D plots in R在 R 中为 3D 绘图重构数据框
【发布时间】:2015-03-30 02:43:28
【问题描述】:

我经常意识到 3D 图并不是呈现一组数据的最有效方式,但我之前为特定数据集制作的 2D 图似乎表明 3D 图有助于将信息分解为更多用于分析的不同聚类。话虽这么说,我从来没有在 R 中这样做过,并且在使用 plot3d() 制作 3D 散点图之前我在重组我的数据框时遇到了麻烦。

目前,我的数据框有 2 列和几千行信息。第一列是标识符,A、B、C...,第二列是该标识符的一个测量特征。

ID Area 
A   1.2
A   3.0
A   2.7
B   1.4
B   2.5
C   4.3
C   2.1
C   1.7

我将在 Y 轴上绘制区域。使用 table() 之类的函数,我可以获得 A、B 或 C 出现的次数:(A=3,B=2,C=3),这个值将成为所有 ID 的 x 坐标结果。但我想做的是将这些信息也放入第三列,为给定的 x 坐标分配一个唯一的 z。换句话说,Z 应该表示给定 X 出现了多少次,并且对于特定 X 的每个新实例都会增加 1。最终,原因是特定 X 内的所有对象的面积值 (y) ID 在唯一的 x,z 坐标上相互堆叠。这就是我卡住的地方。 本质上,我希望给定上述输入的最终数据帧输出如下所示:

ID(x) Area(y)  Z
    3    1.2   1
    3    3.0   1
    3    2.7   1
    2    1.4   1
    2    2.5   1
    3    4.3   2
    3    2.1   2
    3    1.7   2 

【问题讨论】:

  • Z 列不应该是[1, 1, 1, 2, 2, 3, 3, 3]吗?
  • 不,X 表示具有特定 ID 的对象的数量,Z 表示给定 X 出现的次数。对于第一组 3,z=1,因为这是第一组 3。当 x=2 时 Z 再次为 1,因为这是 2 第一次出现。
  • @akrun,照顾它,谢谢提示
  • @MilesW 使用merge 的两个数据集中可能都不存在该列。请检查其中一个数据集中是否存在ID 的前导/滞后空间。还有stackoverflow.com/questions/21708282/…
  • @MilesW 如果您无法找出问题所在,您可以使用重现错误的小数据集的 dput 输出来更新帖子。 IE。 dput(droplevels(head(yourdata,20)))

标签: r dataframe scatter-plot


【解决方案1】:

我们可以通过几种方式做到这一点。

1.基础 R - 聚合/平均

我们可以使用aggregate 获取“ID”列中每个元素(“IDx”)的长度,通过基于重复元素创建“Z”列来转换输出数据集(“dfN”) “IDx”和“合并”“dfN”与原始数据集“df1”

dfN <- aggregate(cbind(IDx=seq_along(ID))~ID, df1, FUN=length)
dfN$Z <- with(dfN, ave(IDx, IDx, FUN=function(x) cumsum(duplicated(x))+1L))
 merge(df1, dfN, by='ID')[-1]
 #  Area IDx Z
 #1  1.2   3 1
 #2  3.0   3 1
 #3  2.7   3 1
 #4  1.4   2 1
 #5  2.5   2 1
 #6  4.3   3 2
 #7  2.1   3 2
 #8  1.7   3 2

2。基础 R - ave/rle

我们可以使用ave 创建'IDx' 列,然后使用`rle/inverse.rle' 创建'Z' 列

 df1$IDx <- with(df1, ave(seq_along(ID), ID, FUN=length))
 v1 <- with(df1, paste0(ID, IDx))
 df1$Z <- inverse.rle(within.list(rle(v1), values <-ave(lengths, 
             lengths, FUN=function(x) cumsum(duplicated(x))+1L)))
 df1
 #  ID Area IDx Z
 #1  A  1.2   3 1
 #2  A  3.0   3 1
 #3  A  2.7   3 1
 #4  B  1.4   2 1
 #5  B  2.5   2 1
 #6  C  4.3   3 2
 #7  C  2.1   3 2
 #8  C  1.7   3 2

3.数据表

将“data.frame”转换为“data.table”(setDT),创建“IDx”,即nrows(.N),按“ID”分组。基于“IDx”中的重复元素,我们可以创建“Z”列。设置key为'ID'(setkey),加入'df1',把不需要的列赋值为NULL(ID:= NULL

library(data.table)
setkey(setDT(df1)[, list(IDx=.N), by = ID][, IDx1:= IDx][,
     list(ID,Z=cumsum(duplicated(IDx1))+1L) , IDx], ID)[df1][, ID := NULL][]

#   IDx Z Area
#1:   3 1  1.2
#2:   3 1  3.0
#3:   3 1  2.7
#4:   2 1  1.4
#5:   2 1  2.5
#6:   3 2  4.3
#7:   3 2  2.1
#8:   3 2  1.7

4. dplyr

思路与上面类似。我们使用 left_join

而不是“合并”
library(dplyr)
left_join(df1, 
            df1 %>% 
              group_by(ID) %>% 
              summarise(IDx=n()) %>% 
              group_by(IDx) %>%
              mutate(Z=cumsum(duplicated(IDx))+1L), by='ID') %>% 
              select(-ID)
 #  Area IDx Z
 #1  1.2   3 1
 #2  3.0   3 1
 #3  2.7   3 1
 #4  1.4   2 1
 #5  2.5   2 1
 #6  4.3   3 2
 #7  2.1   3 2
 #8  1.7   3 2

注意:用另一个数据集“df2”对此进行了测试

数据

df1 <- structure(list(ID = c("A", "A", "A", "B", "B", "C", "C", "C"), 
Area = c(1.2, 3, 2.7, 1.4, 2.5, 4.3, 2.1, 1.7)), .Names = c("ID", 
"Area"), class = "data.frame", row.names = c(NA, -8L))

df2 <-  structure(list(ID = c("A", "A", "A", "B", "B", "C", "C", "C", 
"D", "D", "D", "E", "E", "F"), Area = c(1.2, 3, 2.7, 1.4, 2.5, 
4.3, 2.1, 1.7, 1.2, 1.4, 2.1, 1.2, 1.5, 2.3)), .Names = c("ID", 
"Area"), class = "data.frame", row.names = c(NA, -14L))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 2016-11-26
    • 2016-08-04
    相关资源
    最近更新 更多