为R中的3D绘图重新构造数据帧

为R中的3D绘图重新构造数据帧,r,dataframe,scatter-plot,R,Dataframe,Scatter Plot,我经常意识到,3D绘图并不是表示一组数据的最有效方式,但我之前为特定数据集绘制的2D绘图似乎表明,3D绘图有助于将信息分解为更清晰的聚类进行分析。也就是说,我从来没有在R中这样做过,在使用plot3d()制作3D散点图之前,我很难重新构造数据帧 目前,我的数据框有两列和几千行信息。第一列是一个标识符,A,B,C。。。第2列是该标识符的一个度量特征 前 我将在Y轴上绘制该区域。使用类似table()的函数,我可以得到a、B或C出现的次数:(a=3、B=2、C=3),该值将成为所有ID的x坐标。但是

我经常意识到,3D绘图并不是表示一组数据的最有效方式,但我之前为特定数据集绘制的2D绘图似乎表明,3D绘图有助于将信息分解为更清晰的聚类进行分析。也就是说,我从来没有在R中这样做过,在使用plot3d()制作3D散点图之前,我很难重新构造数据帧

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

我将在Y轴上绘制该区域。使用类似table()的函数,我可以得到a、B或C出现的次数:(a=3、B=2、C=3),该值将成为所有ID的x坐标。但是我想做的是把这些信息也放进第三列,为给定的x坐标指定一个唯一的z。换句话说,Z应该表示给定X出现的次数,并且对于特定X的每个新实例,Z将增加1。最终,原因是特定ID内所有对象的面积值(y)在唯一的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 

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

1。基本R-聚合/平均值

我们可以使用
aggregate
获取“ID”列中每个元素(“IDx”)的长度,通过基于“IDx”中的重复元素创建“Z”列来转换输出数据集(“dfN”),并将“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
3。数据表

将“data.frame”转换为“data.table”(
setDT
),创建“IDx”,即按“ID”分组的nrows(
.N
)。基于“IDx”中的重复元素,我们可以创建“Z”列。将键设置为“ID”(
setkey
),与“df1”连接,并将不必要的列分配给NULL(
ID:=NULL

4。dplyr

这个想法与上面的类似。我们使用
left\u 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列Z不应该是
[1,1,1,2,2,3,3]
?否,X表示具有特定ID的对象的数量,Z表示给定X出现的次数。对于第一组3,z=1,因为这是第一组3。当x=2时,Z又是1,因为这是2第一次出现。@akrun,处理好了,谢谢你的帮助tip@MilesW使用
merge
时,两个数据集中可能都不存在该列。请检查其中一个数据集中是否有
ID
的前置/后置空格。另外@MilesW如果你不能找出问题所在,你可以用一个小数据集的dput输出来更新帖子,这个小数据集会重现错误。也就是说,
dput(液滴液位(头部(你的数据,20))
 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
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
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
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))