如何将一个数据框列中的 N 个值交换为任何 N 值和任何 n(行)?
How do I swap N values in one data frame column for any value of N and any n(row)?
我有包含年龄差异列 (AgeDiff
) 的数据框。数据框如下所示:
library("dplyr")
test <- data.frame("Age1"=c(42, 48, 58, 25, 53, 55, 32, 58, 71, 24, 48, 48, 64, 55, 45, 55, 34, 33, 51, 22),
"Age2"=c(8, 2, 1, 16, 14, 1, 11, 14, 0, 5, 2, 10, 16, 13, 3, 4, 8, 13, 8, 5))
test <- test %>%
mutate(AgeDiff = Age1 - Age2)
对于我正在编写的函数,用户可以输入一个拒绝最小差异and/or一个拒绝最大差异。任何小于任一阈值 than/larger 的年龄差异都会产生“超出范围”的年龄差异。
在我所做的工作中,任何小于 18 岁或大于 54 岁的年龄差异都“超出范围”。巧合的是(我对两组年龄都使用了随机数生成器),刚好有两个年龄差太小,两个年龄差太大。
我可以找到“太年轻”或“太老”的最大值,例如通过比较
TooYoung <- test %>%
filter(AgeDiff < 18) %>%
summarise(Count = n()) %>%
pull(Count)
与
TooOld <- test %>%
filter(AgeDiff > 54) %>%
summarise(Count = n()) %>%
pull(Count)
然后计算出哪个值更大。 TooYoung
和 TooOld
中较大的一个给出了我需要在 test
数据中交换的行数。
我可以(预先)对 test
数据框进行排序,以便 AgeDiff
的值递增:
test <- test %>%
arrange(AgeDiff)
这给了我想要的顺序,其中数据框从最极端 AgeDiff
最小值到最极端 AgeDiff
最大值排序。现在我想要做的是将最顶部和最底部的 Age1
值交换为 TooYoung
和 TooOld
的最大值。因为在这个例子中我有 2 个作为我的最大“超出范围”minima/maxima 计数,所以我需要交换:
Age1
在第 1 行中 Age1
在第 20 行中
Age1
在第 2 行中 Age1
在第 19 行中
交换是否导致“超出范围”并不重要AgeDiff
。
交换的数据帧可以是任意长度。要进行的交换次数可以是任何数字,包括 0。所以问题就变成了,对于任何交换值 >0,
Age1
在第 1 行,Age1
在 nrow(foo)
Age1
在第 2 行,Age1
在 nrow(foo)-1
- 等等交换的次数。
AgeDiff
将在交换后重新计算。我的数据框中还有其他变量,例如 Sex
,因此仅交换 Age1
值很关键。
行的重新排序并不重要。唯一的要求是解决方案交换正确的 Age1
值对。
我搜索过类似的问题,但发现的问题却大相径庭。其他问题是, , , swap of two randomly selected rows, value swaps based on grouping variables。在我的问题中,交换的数量肯定会计算出来,但人口之间的数量不同,要交换的 Age1
值会有所不同,要交换的 Age1
值的数量必须恰好是最大值“超出范围”计数,并且没有分组变量。
编辑添加:假设您有我的数据并已完成安排,您会看到第 1 行如下所示:
Age1 Age2 AgeDiff
25 16 9
第 20 行看起来像:
Age1 Age2 AgeDiff
71 0 71
Post 交换这两行将是:
第 1 行:
Age1 Age2 AgeDiff
71 16 9
第 20 行:
Age1 Age2 AgeDiff
25 0 71
所以只有两个 Age1
值被交换了。
然后第 2 行和第 19 行交换,以
结束
第 2 行
Age1 Age2 AgeDiff
58 5 17
第 19 行
Age1 Age2 AgeDiff
22 1 57
AgeDiff
列被忽略,因为它在完成交换后重新计算。
(我也错过了初始数据框也应该被称为测试,我现在已经修复了。)
我确定有更简洁的方法可以做到这一点,但是....
library("dplyr")
test <- data.frame("Age1"=c(42, 48, 58, 25, 53, 55, 32, 58, 71, 24, 48, 48, 64, 55, 45, 55, 34, 33, 51, 22),
"Age2"=c(8, 2, 1, 16, 14, 1, 11, 14, 0, 5, 2, 10, 16, 13, 3, 4, 8, 13, 8, 5))
test <- test %>%
mutate(AgeDiff = Age1 - Age2) %>%
arrange(AgeDiff) %>%
dplyr::mutate(row_no = row_number())
test
swap <- function(df) {
TooYoung <- df %>%
filter(AgeDiff < 18) %>%
summarise(Count = n()) %>%
pull(Count)
TooOld <- df %>%
filter(AgeDiff > 54) %>%
summarise(Count = n()) %>%
pull(Count)
top_bottom <- max(TooYoung, TooOld)
df2 <- df %>%
filter(row_number() > max(row_number()) - top_bottom | row_number() <= top_bottom) %>%
mutate(final_age1 = Age1) %>%
dplyr::select(final_age1, row_no)
df2$row_no <- sort(df2$row_no, decreasing = T)
df_final <- df %>%
left_join(df2) %>%
mutate(final_age1 = ifelse(is.na(final_age1), Age1, final_age1)) %>%
dplyr::select(-Age1, -row_no)
df_final
}
swap(test)
我认为哪个能满足您的需求?
# Joining, by = "row_no"
# Age2 AgeDiff final_age1
# 1 16 9 71
# 2 5 17 58
# 3 5 19 24
# 4 13 20 33
# 5 11 21 32
# 6 8 26 34
# 7 8 34 42
# 8 10 38 48
# 9 14 39 53
# 10 13 42 55
# 11 3 42 45
# 12 8 43 51
# 13 14 44 58
# 14 2 46 48
# 15 2 46 48
# 16 16 48 64
# 17 4 51 55
# 18 1 54 55
# 19 1 57 22
# 20 0 71 25
我有包含年龄差异列 (AgeDiff
) 的数据框。数据框如下所示:
library("dplyr")
test <- data.frame("Age1"=c(42, 48, 58, 25, 53, 55, 32, 58, 71, 24, 48, 48, 64, 55, 45, 55, 34, 33, 51, 22),
"Age2"=c(8, 2, 1, 16, 14, 1, 11, 14, 0, 5, 2, 10, 16, 13, 3, 4, 8, 13, 8, 5))
test <- test %>%
mutate(AgeDiff = Age1 - Age2)
对于我正在编写的函数,用户可以输入一个拒绝最小差异and/or一个拒绝最大差异。任何小于任一阈值 than/larger 的年龄差异都会产生“超出范围”的年龄差异。
在我所做的工作中,任何小于 18 岁或大于 54 岁的年龄差异都“超出范围”。巧合的是(我对两组年龄都使用了随机数生成器),刚好有两个年龄差太小,两个年龄差太大。
我可以找到“太年轻”或“太老”的最大值,例如通过比较
TooYoung <- test %>%
filter(AgeDiff < 18) %>%
summarise(Count = n()) %>%
pull(Count)
与
TooOld <- test %>%
filter(AgeDiff > 54) %>%
summarise(Count = n()) %>%
pull(Count)
然后计算出哪个值更大。 TooYoung
和 TooOld
中较大的一个给出了我需要在 test
数据中交换的行数。
我可以(预先)对 test
数据框进行排序,以便 AgeDiff
的值递增:
test <- test %>%
arrange(AgeDiff)
这给了我想要的顺序,其中数据框从最极端 AgeDiff
最小值到最极端 AgeDiff
最大值排序。现在我想要做的是将最顶部和最底部的 Age1
值交换为 TooYoung
和 TooOld
的最大值。因为在这个例子中我有 2 个作为我的最大“超出范围”minima/maxima 计数,所以我需要交换:
Age1
在第 1 行中Age1
在第 20 行中Age1
在第 2 行中Age1
在第 19 行中
交换是否导致“超出范围”并不重要AgeDiff
。
交换的数据帧可以是任意长度。要进行的交换次数可以是任何数字,包括 0。所以问题就变成了,对于任何交换值 >0,
Age1
在第 1 行,Age1
在nrow(foo)
Age1
在第 2 行,Age1
在nrow(foo)-1
- 等等交换的次数。
AgeDiff
将在交换后重新计算。我的数据框中还有其他变量,例如 Sex
,因此仅交换 Age1
值很关键。
行的重新排序并不重要。唯一的要求是解决方案交换正确的 Age1
值对。
我搜索过类似的问题,但发现的问题却大相径庭。其他问题是Age1
值会有所不同,要交换的 Age1
值的数量必须恰好是最大值“超出范围”计数,并且没有分组变量。
编辑添加:假设您有我的数据并已完成安排,您会看到第 1 行如下所示:
Age1 Age2 AgeDiff
25 16 9
第 20 行看起来像:
Age1 Age2 AgeDiff
71 0 71
Post 交换这两行将是: 第 1 行:
Age1 Age2 AgeDiff
71 16 9
第 20 行:
Age1 Age2 AgeDiff
25 0 71
所以只有两个 Age1
值被交换了。
然后第 2 行和第 19 行交换,以
结束第 2 行
Age1 Age2 AgeDiff
58 5 17
第 19 行
Age1 Age2 AgeDiff
22 1 57
AgeDiff
列被忽略,因为它在完成交换后重新计算。
(我也错过了初始数据框也应该被称为测试,我现在已经修复了。)
我确定有更简洁的方法可以做到这一点,但是....
library("dplyr")
test <- data.frame("Age1"=c(42, 48, 58, 25, 53, 55, 32, 58, 71, 24, 48, 48, 64, 55, 45, 55, 34, 33, 51, 22),
"Age2"=c(8, 2, 1, 16, 14, 1, 11, 14, 0, 5, 2, 10, 16, 13, 3, 4, 8, 13, 8, 5))
test <- test %>%
mutate(AgeDiff = Age1 - Age2) %>%
arrange(AgeDiff) %>%
dplyr::mutate(row_no = row_number())
test
swap <- function(df) {
TooYoung <- df %>%
filter(AgeDiff < 18) %>%
summarise(Count = n()) %>%
pull(Count)
TooOld <- df %>%
filter(AgeDiff > 54) %>%
summarise(Count = n()) %>%
pull(Count)
top_bottom <- max(TooYoung, TooOld)
df2 <- df %>%
filter(row_number() > max(row_number()) - top_bottom | row_number() <= top_bottom) %>%
mutate(final_age1 = Age1) %>%
dplyr::select(final_age1, row_no)
df2$row_no <- sort(df2$row_no, decreasing = T)
df_final <- df %>%
left_join(df2) %>%
mutate(final_age1 = ifelse(is.na(final_age1), Age1, final_age1)) %>%
dplyr::select(-Age1, -row_no)
df_final
}
swap(test)
我认为哪个能满足您的需求?
# Joining, by = "row_no"
# Age2 AgeDiff final_age1
# 1 16 9 71
# 2 5 17 58
# 3 5 19 24
# 4 13 20 33
# 5 11 21 32
# 6 8 26 34
# 7 8 34 42
# 8 10 38 48
# 9 14 39 53
# 10 13 42 55
# 11 3 42 45
# 12 8 43 51
# 13 14 44 58
# 14 2 46 48
# 15 2 46 48
# 16 16 48 64
# 17 4 51 55
# 18 1 54 55
# 19 1 57 22
# 20 0 71 25