在R中重构3D图的数据框

时间:2015-03-30 02:43:28

标签: r dataframe scatter-plot

我经常意识到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.最终,原因是特定于所有对象的区域值(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 

1 个答案:

答案 0 :(得分:2)

我们可以通过两种方式实现这一目标。

<强> 1。基础R - 聚合/ ave

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

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

我们可以创建&#39; IDx&#39;使用ave的列,然后使用`rle / inverse.rle&#39;创造&#39; Z&#39;柱

 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.table

转换&#39; data.frame&#39;到&#39; data.table&#39; (setDT),创建&#39; IDx&#39;即nrows(.N),按ID&#39;分组。根据IDx&#39;中的重复元素,我们可以创建&#39; Z&#39;柱。将密钥设置为&#39; ID&#39; (setkey),加入&#39; df1&#39;,并将不必要的列指定为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

代替&#39;合并&#39;
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

注意:使用其他数据集对此进行测试&#39; df2&#39;

数据

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))