在R中顺序排序后,将标签分配给列中的值

时间:2017-09-20 17:17:07

标签: r dataframe columnsorting

我的数据框看起来像可以使用以下代码复制的数据框:

 reproduce.df <- rbind.data.frame(replicate(6,sample(1:50, 50, rep = TRUE)),replicate(6,sample(NA, 5, rep = TRUE)),replicate(6,sample(1:50, 50, rep = TRUE)))
  1. 我想将第1列中的数据分成3个部分,并根据最低到最高的tercile为它们分配3个标签。 (让我们说标签是1,2,3)
  2. 在为第1列中的数据分配标签后,我想在第2列中分配标签,方法是先按三个变量中的每一个对第1列中的值进行分组,然后按照这3个组中的每个变量分配名为1到3的标签。 terciles。 例如。第1列中最低的tercile值将具有标签&#34; 1&#34;。对于第1列中的所有1,我想根据第2列中的值创建terciles并分配标签&#34; 1&#34;,&#34; 2&#34;,&#34; 3&# 34;给他们。
  3. 在合并第1列和第1列中数据的标签后,在第3列中再次重复此过程。这样,对于第三列数据,我们有27个唯一标签。
  4. 在第4至6列中再次重复该过程。
  5. 我尝试过: 使用剪切功能在第1列中分配标签并将其添加到数据框中。代码如下:

    labels.v1 <- cut(reproduce.df[,1], quantile(reproduce.df[,1], seq(from = 0, to = 1, length.out = 4), na.rm = TRUE), labels = seq(1:3), include.lowest = TRUE)
    
    reproduce.df2 <- cbind.data.frame(reproduce.df,labels.v1)
    

    但是,我无法将此逻辑扩展到下一步。 对于下一步,我使用&#39; by&#39;功能是根据第1列标签将数据框分成3个部分,然后为这3个部分分配标签。

    by(reproduce.df2$V2, reproduce.df2$labels.v1, FUN = function(x) cut(x, quantile(x, seq(from=0,to=1,length.out = 4), na.rm = TRUE), labels = c("1","2","3"), include.lowest = TRUE))
    

    虽然这样可行,但它提供的输出是列表格式,不能直接与数据帧合并。此外,它从数据帧中删除NA,我想保留NA,因为这些列是较大数据帧的一部分,我想只是合并标签与该数据帧。

    我如何在R?

    中执行此过程

2 个答案:

答案 0 :(得分:1)

如果真的想要使用基础R,可以这样做,但dplyr甚至data.table会更容易。

您确定的第一个问题是by会返回一个列表。您可以简单地unlist()输出以获得向量。 这会产生新问题 - 您的原始数据未排序,因此未列出的数据不会按正确的顺序排列。所以,首先我们需要对数据进行排序。

reproduce.df2 <- cbind.data.frame(reproduce.df,labels.v1)[order(labels.v1),]
labels.v2 <- unlist(by(reproduce.df2$V2, reproduce.df2$labels.v1, FUN = function(x) cut(x, quantile(x, seq(from=0,to=1,length.out = 4), na.rm = TRUE), labels = c("1","2","3"), include.lowest = TRUE)))

但是现在你遇到了一个新问题 - 你的数据框架的NA,特别是labels.v1没有被包含在内,所以labels.v2现在太短了。您需要过滤掉任何具有NA的行才能使其正常工作。对于接下来的步骤,您需要将标签列粘贴在一起进行排序,以使嵌套排序正常工作。

那么使用dplyr呢?

library(dplyr)
set.seed(1001)
reproduce.df <- rbind.data.frame(replicate(6,sample(1:50, 50, rep = TRUE)),replicate(6,sample(NA, 5, rep = TRUE)),replicate(6,sample(1:50, 50, rep = TRUE)))
breaks <- seq(0,1,length.out=4)
reproduce.df <- mutate(reproduce.df,labels.v1 = cut(V1,quantile(V1,breaks,na.rm=T),labels=FALSE,include.lowest=TRUE))
reproduce.df <- group_by(reproduce.df,labels.v1)
reproduce.df <- mutate(reproduce.df,labels.v2 = cut(V2,breaks=quantile(V2,breaks,na.rm=T),labels=FALSE,include.lowest=TRUE))
reproduce.df <- group_by(reproduce.df,labels.v1,labels.v2)
reproduce.df <- mutate(reproduce.df,labels.v3 = cut(V3,breaks=quantile(V3,breaks,na.rm=T),labels=FALSE,include.lowest=TRUE))

在每一步中,您都会将之前的标签添加到group_bymutate(创建变量)新标签。

注意 - 我设置了labels = FALSE因为它没有指定标签1:3。这样它无论如何都只输出1到3的整数。

您可以在上面的代码末尾看到输出。

> arrange(reproduce.df,labels.v1,labels.v2,labels.v3)
# A tibble: 105 x 9
# Groups:   labels.v1, labels.v2 [10]
      V1    V2    V3    V4    V5    V6 labels.v1 labels.v2 labels.v3
   <int> <int> <int> <int> <int> <int>     <int>     <int>     <int>
 1     5     3     3     9    10    34         1         1         1
 2     3     2    13    15     7    11         1         1         1
 3    14     5    24    16    19     3         1         1         1
 4     5    14    20     3    45    34         1         1         1
 5     4    17     3    15    16    12         1         1         1
 6     1    15    41    15    48    47         1         1         2
 7    15     4    31    29    39    25         1         1         2
 8    15     8    26    41    42     8         1         1         2
 9     4    11    28    45    11    46         1         1         2
10     5    13    46    42    34    18         1         1         3
# ... with 95 more rows

答案 1 :(得分:1)

有...

library(data.table)
setDT(DF)

DF[, v := ""]    
for (k in names(DF)[1:6]){
  DF[!is.na(get(k)), v := paste0(v, cut(get(k), 3, FALSE)), by=v]
  DF[is.na(get(k)), v := paste0(v, "-")]
}

     V1 V2 V3 V4 V5 V6      v
  1: 42 33 10  8 26 35 321122
  2: 21 35 42 46  9  2 233322
  3: 10 26 18 25 40 17 121232
  4: 22 35 26 34  3  1 232322
  5: 26 30 23  2 23 24 222122
 ---                         
101: 25 26 18  8 31 24 221123
102:  2 37 13 28 34 33 131232
103: 10  5 14 20 33 29 111122
104: 27 50 18  1 18 33 231112
105: 16 42 23  3 14 35 132122

我尝试使用基础R中的ave来执行此操作,但处理起来太烦人了。

使用替换值-,因为如果某些列丢失而其他列不在一行内,则留空或NA无效。