R根据先前列的比较生成值
R Generating values based on comparison of previous columns
我希望生成一个列 (Min),它可以找到 selected 名称列的最小值,并提取该列的名称作为其值。以下是示例数据框:
Amy Abe Donna Racheal Mike Min u
5 34 54 56 23 Amy 0
43 11 3 33 21 Donna 1
54 32 21 54 1 Mike 1
21 5 43 32 21 Abe 1
32 21 23 5 32 Racheal 0
43 2 2 13 45 Abe Donna 1
.
.
.
u 列只是数据集末尾的一列。数据集相当大,因此我试图找到一种有效的方法来生成列 Min。
我想到的代码:
MinData <- Data %>% mutate(Min =
min(colnames(Data)[1:5]))
这只提取列的名称。我应该添加什么以使列能够比较每行中的值和 select 具有最小值的列名称?
以下是我的处理方法:
library(tidyverse) # we use dplyr and tidyr
Data <- Data %>%
mutate(row = 1:length(u))
MinData <- Data %>%
gather(name, score, -u, -row, -Min) %>%
group_by(row) %>%
summarize(Min2 = paste(name[score == min(score)], collapse = " ")) %>% # called "Min2" to differentiate it from the "Min" column provided in the example.
left_join(df %>% mutate(row = 1:length(u)), .)
我会使用 apply 函数:)
设置我们的名称向量
person_names= names(df[,1:5]) #Presumably the column names are the names
1:5
就在那里,以防您的数据集中有其他列您不想考虑进行最小检查。
现在我们可以在自定义函数上使用 apply,该函数 return 每一行中具有最低值的列中的名称。
df$Min <- apply(df[,1:5], 1, function(x){person_names[which.min(x)]})
我们的自定义函数正如我已经描述的那样,apply 只是将函数应用于数据框或矩阵的每一列或每一行。第二个参数 1
表示行,如果我们想要列,我们可以将其更改为 2
.
which.min
只是 returns 最小值所在的元素编号。 person_names
按顺序排列我们的名字,which.min
return 是一个数字,表示哪个名字的值最小。
如果你想取消 person_names
变量,你可以将这一切压缩成一个单行解决方案。
df$Min <- apply(df[,1:5], 1, function(x){names(df[,1:5])[which.min(x)]})
如果您只有 5 个名称列,请删除 1:5
,如果您在任何地方都有列,只需将其替换为您的列名或编号的向量。
编辑: 我看到了您对另一个答案的评论。为了适应关系,我将更改自定义函数,以便它检查所有具有最小值 x 的匹配项,然后将它们与一些自定义分隔符粘贴在一起。我还将修改您的数据,以便 Donna 和 Racheal 并排在第二行。
df <- read.table(text = 'Amy Abe Donna Racheal Mike Min u
5 34 54 56 23 Amy 0
43 11 3 3 21 Donna 1
54 32 21 54 1 Mike 1
21 5 43 32 21 Abe 1
32 21 23 5 32 Racheal 0', header = T)
person_names <- names(df[,1:5])
df$Min <- apply(df[,1:5], 1, function(x){paste(person_names[x == min(x)],
collapse = ", ")})
> df
Amy Abe Donna Racheal Mike Min u
1 5 34 54 56 23 Amy 0
2 43 11 3 3 21 Donna, Racheal 1
3 54 32 21 54 1 Mike 1
4 21 5 43 32 21 Abe 1
5 32 21 23 5 32 Racheal 0
我已经将 collapse
参数设置为“,”,这是我任意选择的分隔符。您可以将其调整为 space " ",或分号,或您想要的任何内容。
同样,通过删除 person_names
.
的单独行,可以将其压缩为一行答案
您的原始数据:
df1 <- structure(list(Amy = c(5L, 43L, 54L, 21L, 32L, 43L),
Abe = c(34L, 11L, 32L, 5L, 21L, 2L),
Donna = c(54L, 3L, 21L, 43L, 23L, 2L),
Racheal = c(56L, 33L, 54L, 32L, 5L, 13L),
Mike = c(23L, 21L, 1L, 21L, 32L, 45L),
u = c(0, 1, 1, 1, 0, 1)),
row.names = c(NA, -6L),
class = "data.frame")
我们可以使用 tidyr
和 dplyr
从宽转换为长,进行计算和聚合,然后在最后将它们重新组合在一起。
library(dplyr)
library(tidyr)
df1 %>%
gather(name, value, -u) %>% # convert from wide to long
group_by(name) %>%
mutate(idx = row_number()) %>% # add a grouping variable
ungroup() %>%
group_by(idx) %>%
mutate(Min = min(value)) %>% # calculate min per group (= per row)
filter(value == Min) %>% # keep names with value = Min
arrange(idx) %>% # order rows as original data
select(idx, Min = name) %>%
summarise(Min = paste(Min, collapse = ",")) %>% # combine names where Min tied
ungroup() %>%
select(Min) %>%
bind_cols(df1, .) # combine column Min (names) with
# original data
Amy Abe Donna Racheal Mike u Min
1 5 34 54 56 23 0 Amy
2 43 11 3 33 21 1 Donna
3 54 32 21 54 1 1 Mike
4 21 5 43 32 21 1 Abe
5 32 21 23 5 32 0 Racheal
6 43 2 2 13 45 1 Abe,Donna
我希望生成一个列 (Min),它可以找到 selected 名称列的最小值,并提取该列的名称作为其值。以下是示例数据框:
Amy Abe Donna Racheal Mike Min u
5 34 54 56 23 Amy 0
43 11 3 33 21 Donna 1
54 32 21 54 1 Mike 1
21 5 43 32 21 Abe 1
32 21 23 5 32 Racheal 0
43 2 2 13 45 Abe Donna 1
.
.
.
u 列只是数据集末尾的一列。数据集相当大,因此我试图找到一种有效的方法来生成列 Min。
我想到的代码:
MinData <- Data %>% mutate(Min =
min(colnames(Data)[1:5]))
这只提取列的名称。我应该添加什么以使列能够比较每行中的值和 select 具有最小值的列名称?
以下是我的处理方法:
library(tidyverse) # we use dplyr and tidyr
Data <- Data %>%
mutate(row = 1:length(u))
MinData <- Data %>%
gather(name, score, -u, -row, -Min) %>%
group_by(row) %>%
summarize(Min2 = paste(name[score == min(score)], collapse = " ")) %>% # called "Min2" to differentiate it from the "Min" column provided in the example.
left_join(df %>% mutate(row = 1:length(u)), .)
我会使用 apply 函数:)
设置我们的名称向量
person_names= names(df[,1:5]) #Presumably the column names are the names
1:5
就在那里,以防您的数据集中有其他列您不想考虑进行最小检查。
现在我们可以在自定义函数上使用 apply,该函数 return 每一行中具有最低值的列中的名称。
df$Min <- apply(df[,1:5], 1, function(x){person_names[which.min(x)]})
我们的自定义函数正如我已经描述的那样,apply 只是将函数应用于数据框或矩阵的每一列或每一行。第二个参数 1
表示行,如果我们想要列,我们可以将其更改为 2
.
which.min
只是 returns 最小值所在的元素编号。 person_names
按顺序排列我们的名字,which.min
return 是一个数字,表示哪个名字的值最小。
如果你想取消 person_names
变量,你可以将这一切压缩成一个单行解决方案。
df$Min <- apply(df[,1:5], 1, function(x){names(df[,1:5])[which.min(x)]})
如果您只有 5 个名称列,请删除 1:5
,如果您在任何地方都有列,只需将其替换为您的列名或编号的向量。
编辑: 我看到了您对另一个答案的评论。为了适应关系,我将更改自定义函数,以便它检查所有具有最小值 x 的匹配项,然后将它们与一些自定义分隔符粘贴在一起。我还将修改您的数据,以便 Donna 和 Racheal 并排在第二行。
df <- read.table(text = 'Amy Abe Donna Racheal Mike Min u
5 34 54 56 23 Amy 0
43 11 3 3 21 Donna 1
54 32 21 54 1 Mike 1
21 5 43 32 21 Abe 1
32 21 23 5 32 Racheal 0', header = T)
person_names <- names(df[,1:5])
df$Min <- apply(df[,1:5], 1, function(x){paste(person_names[x == min(x)],
collapse = ", ")})
> df
Amy Abe Donna Racheal Mike Min u
1 5 34 54 56 23 Amy 0
2 43 11 3 3 21 Donna, Racheal 1
3 54 32 21 54 1 Mike 1
4 21 5 43 32 21 Abe 1
5 32 21 23 5 32 Racheal 0
我已经将 collapse
参数设置为“,”,这是我任意选择的分隔符。您可以将其调整为 space " ",或分号,或您想要的任何内容。
同样,通过删除 person_names
.
您的原始数据:
df1 <- structure(list(Amy = c(5L, 43L, 54L, 21L, 32L, 43L),
Abe = c(34L, 11L, 32L, 5L, 21L, 2L),
Donna = c(54L, 3L, 21L, 43L, 23L, 2L),
Racheal = c(56L, 33L, 54L, 32L, 5L, 13L),
Mike = c(23L, 21L, 1L, 21L, 32L, 45L),
u = c(0, 1, 1, 1, 0, 1)),
row.names = c(NA, -6L),
class = "data.frame")
我们可以使用 tidyr
和 dplyr
从宽转换为长,进行计算和聚合,然后在最后将它们重新组合在一起。
library(dplyr)
library(tidyr)
df1 %>%
gather(name, value, -u) %>% # convert from wide to long
group_by(name) %>%
mutate(idx = row_number()) %>% # add a grouping variable
ungroup() %>%
group_by(idx) %>%
mutate(Min = min(value)) %>% # calculate min per group (= per row)
filter(value == Min) %>% # keep names with value = Min
arrange(idx) %>% # order rows as original data
select(idx, Min = name) %>%
summarise(Min = paste(Min, collapse = ",")) %>% # combine names where Min tied
ungroup() %>%
select(Min) %>%
bind_cols(df1, .) # combine column Min (names) with
# original data
Amy Abe Donna Racheal Mike u Min
1 5 34 54 56 23 0 Amy
2 43 11 3 33 21 1 Donna
3 54 32 21 54 1 1 Mike
4 21 5 43 32 21 1 Abe
5 32 21 23 5 32 0 Racheal
6 43 2 2 13 45 1 Abe,Donna