我有包含年龄差异列(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)对于我正在编写的函数,用户可以输入拒绝最小差和/或拒绝最大差。任何小于/大于任一阈值的年龄差异都会造成“范围外”的年龄差异。
在我所做的工作中,任何小于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作为我的最大“范围外”最小值/最大值,所以我需要交换:
Age1在第1行,Age1在行,20Age1在第2行,Age1在第19行,如果交换导致“超出作用域”AgeDiff,这并不重要。
交换区的数据帧可以是任意长度。要进行的掉期数量可以是任意数字,包括0。所以问题是,对于任何>0的交换值,
Age1在第1行,在nrow(foo)Age1中使用Age1,在第2行中使用Age1,这样就可以获得要进行的交换的数量。AgeDiff将在掉期交易完成后重新计算。我的数据框架中还有其他变量,如Sex,因此只交换Age1值至关重要。
行的重新排序并不重要。唯一的要求是解决方案需要交换正确的Age1值对。
我曾寻找过类似的问题,但我发现的问题完全不同。其他的问题是a two-row swap for an initial percentage of the data frame,a swap of two known values for each other,swapping entire rows,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 71Post交换后这两行将是:第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 57AgeDiff列在完成交换后重新计算时会被忽略。
(我也错过了最初的数据框架也应该被称为test,我现在已经修正了。)
发布于 2020-07-01 11:32:09
我肯定有更整洁的方法,但是.
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 25https://stackoverflow.com/questions/62674720
复制相似问题