在 R 中顺序排序后将标签分配给列中的值
Assigning labels to values in columns after sequential sorting in R
我有一个看起来像可以用以下代码复制的数据框:
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 列中的数据分成 3 部分,并根据从最低到最高的三分位数为它们分配 3 个标签。 (假设标签是 1,2,3)
- 为第 1 列中的数据分配标签后,我想在第 2 列中分配标签,方法是首先按三个变量中的每一个对第 1 列中的值进行分组,然后在这 3 组中的每组中分配名为 1 到 3 的标签根据三分位数。
例如。第 1 列中最低的三位数将具有标签“1”。对于第 1 列中的所有 1,我想根据第 2 列中的值创建三分位数,并将标签“1”、“2”、“3”分配给它们。
- 在合并第 1 列和第 2 列中的数据标签后,在第 3 列中再次重复此过程。这样,对于第三列数据,我们有 27 个唯一标签。
- 此过程在第 4 列到第 6 列中再次重复。
我尝试过的:
使用 cut 函数在第 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)
但是,我无法将此逻辑扩展到下一步。
对于下一步,我使用 'by' 函数根据第 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 中执行此过程?
如果你真的只想使用基础 R,这可以做到,但使用 dplyr
甚至 data.table
会容易得多。
您发现的第一个问题是 by
returns 一个列表。您可以简单地 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
的 NA 未包含在内,因此 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_by
并 mutate
(创建变量)新标签。
注意 - 我设置了 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
有...
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 没有意义。
我有一个看起来像可以用以下代码复制的数据框:
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 列中的数据分成 3 部分,并根据从最低到最高的三分位数为它们分配 3 个标签。 (假设标签是 1,2,3)
- 为第 1 列中的数据分配标签后,我想在第 2 列中分配标签,方法是首先按三个变量中的每一个对第 1 列中的值进行分组,然后在这 3 组中的每组中分配名为 1 到 3 的标签根据三分位数。 例如。第 1 列中最低的三位数将具有标签“1”。对于第 1 列中的所有 1,我想根据第 2 列中的值创建三分位数,并将标签“1”、“2”、“3”分配给它们。
- 在合并第 1 列和第 2 列中的数据标签后,在第 3 列中再次重复此过程。这样,对于第三列数据,我们有 27 个唯一标签。
- 此过程在第 4 列到第 6 列中再次重复。
我尝试过的: 使用 cut 函数在第 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)
但是,我无法将此逻辑扩展到下一步。 对于下一步,我使用 'by' 函数根据第 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 中执行此过程?
如果你真的只想使用基础 R,这可以做到,但使用 dplyr
甚至 data.table
会容易得多。
您发现的第一个问题是 by
returns 一个列表。您可以简单地 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
的 NA 未包含在内,因此 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_by
并 mutate
(创建变量)新标签。
注意 - 我设置了 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
有...
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 没有意义。