在 R 中使用 Vectors、现有变量和 mapply 创建多个新变量
Creating multiple new variables using Vectors, existing variables, and mapply in R
我是 R 的新手,我正在尝试在我的数据集中创建一个新的 columns/variables,df
,使用来自我的数据集中已经存在的多个列的信息。我希望使用 mapply
函数来执行此操作。这是指在某人的右侧和左侧进行的某些测量的数据。然而,这些方面中只有一个受到影响,并且由 df$laterality
定义。最终,我想创建新的 variable/columns,它将从测量中收集的数据定义为从受影响的一侧收集的数据。
我的数据,经过简化,基本上如下所示
recordID <- c(1, 2, 3, 4)
laterality <- c(right, right, left, right)
right_1_measure <- c(2.3, 3.4, 1.7, 2.4)
right_2_measure <- c(1.3, 2.2, 3.1, 4.1)
right_3_measure <- c(2.7, 2.8, 4.2, 3.9)
left_1_measure <- c(1.5, 2.6, 4.5, 2.8)
left_2_measure <- c(1.1, 3.4, 3.5, 2.6)
left_3_measure <- c (2.6, 2.8, 3.6, 1.6)
df <- data.frame(recordID, laterality, right_1_measure, right_2_measure, right_3_measure, left_1_measure, left_2_measure, left_3_measure)
然后我创建了一个列名称的向量,我希望循环通过它来创建新的“受影响的”variable/columns,我将根据之前定义的变量命名,但添加前缀“aff” .我还创建了一个包含我希望赋予新列的名称的向量。
right_vars <- c("right_1_measure", "right_2_measure" , "right_3_measure")
left_vars <- c("left_1_measure", "left_2_measure" , "left_3_measure")
aff_vars <- c("aff_1_measure", "aff_2_measure", "aff_3_measure")
然后我创建了我计划用来根据 df$laterality
有条件地创建新列的函数
aff_var_create <- function (x, y, z){
df$x <- ifelse(df$laterality == "Right" , df$y, ifelse (df$laterality == "Left", df$z, NA))
}
然后我创建了我的 mapply
代码
mapply(FUN = aff_var_create, x = aff_vars, y = r_vars, z = l_vars)
但是,当我 运行 这样做时,我收到以下错误消息:
Error in ans[ypos] <- rep(yes, length.out = len)[ypos] :
replacement has length zero
In addition: Warning message:
In rep(yes, length.out = len) :
Error in ans[ypos] <- rep(yes, length.out = len)[ypos] :
replacement has length zero
我检查了我的数据框,所有列中都有数据,所以我很困惑为什么 y.pos 的长度为零。
最终,我希望我的数据框如下所示
recordID <- c(1, 2, 3, 4)
laterality <- c(right, right, left, right)
right_1_measure <- c(2.3, 3.4, 1.7, 2.4)
right_2_measure <- c(1.3, 2.2, 3.1, 4.1)
right_3_measure <- c(2.7, 2.8, 4.2, 3.9)
left_1_measure <- c(1.5, 2.6, 4.5, 2.8)
left_2_measure <- c(1.1, 3.4, 3.5, 2.6)
left_3_measure <- c (2.6, 2.8, 3.6, 1.6)
aff_1_measure <- c(2.3, 3.4, 4.5, 2.4)
aff_2_measure <- c(1.3, 2.2, 3.5, 4.1)
aff_3_measure <- c(2.7, 2.8, 3.6, 3.9)
df <- data.frame(recordID, laterality, right_1_measure, right_2_measure, right_3_measure, left_1_measure, left_2_measure, left_3_measure, aff_1_measure, aff_2_measure, aff_3_measure)
如有任何解决此问题或使用其他方法获得类似结果的建议,我们将不胜感激!谢谢。
这不是 mapply
解决方案,但对于此类数据工作,我建议使用 tidyverse
包或至少其中的一部分:
library(dplyr)
library(tidyr)
df %>%
pivot_longer(matches("_\d+_measure"), names_to=c("side", "no"), names_pattern="(\w+)_(\d+)_measure") %>%
filter(laterality == side) %>%
select(-side) %>%
pivot_wider(names_from=no, names_glue="aff_{no}_measure") %>%
full_join(df, by=c("recordID", "laterality"))
哪个returns
# A tibble: 4 x 11
recordID laterality aff_1_measure aff_2_measure aff_3_measure right_1_measure right_2_measure right_3_measure
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 right 2.3 1.3 2.7 2.3 1.3 2.7
2 2 right 3.4 2.2 2.8 3.4 2.2 2.8
3 3 left 4.5 3.5 3.6 1.7 3.1 4.2
4 4 right 2.4 4.1 3.9 2.4 4.1 3.9
# ... with 3 more variables: left_1_measure <dbl>, left_2_measure <dbl>, left_3_measure <dbl>
注意:您可以轻松更改列的顺序,使此输出与您想要的输出匹配。
我做了什么?
- 首先,我们使用
pivot_longer
将数据转换为“长”格式。这使我们能够过滤数据以获得正确的偏侧性。
- 现在我们必须采取措施使用
pivot_wider
创建 aff_n_measure
列。
- 最后,我们使用
full_join
. 将这些新数据与您的旧数据结合起来
您不能使用 $
表示法动态传递字符串值。而是使用 [[
。此外,由于 mapply
不会就地更新数据框,您需要将结果分配给列:
right_vars <- c("right_1_measure", "right_2_measure" , "right_3_measure")
left_vars <- c("left_1_measure", "left_2_measure" , "left_3_measure")
aff_vars <- c("aff_1_measure", "aff_2_measure", "aff_3_measure")
aff_var_create <- function(x, y, z){
ifelse(df$laterality == "right" , df[[y]], ifelse(df$laterality == "left", df[[z]], NA))
}
df[aff_vars] <- mapply(FUN=aff_var_create, x=aff_vars, y=right_vars, z=left_vars)
df
或者,通过使用 [
的索引进行分配。
aff_cols <- paste0("aff_", 1:3, "_measure")
right_cols <- paste0("right_", 1:3, "_measure")
left_cols <- paste0("left_", 1:3, "_measure")
curr_logic <- df$laterality == "right"
# INITIALIZE COLUMNS
df[aff_cols] <- NA
# UPDATE COLUMNS BY INDEX
df[curr_logic , aff_cols] <- df[curr_logic , right_cols]
df[!curr_logic , aff_cols] <- df[!curr_logic, left_cols]
df
更好的是,使用单个 ifelse
调用,因为它可以 运行 向量和矩阵比较对齐到相同的维度(因此,replicate
)。
aff_cols <- paste0("aff_", 1:3, "_measure")
right_cols <- paste0("right_", 1:3, "_measure")
left_cols <- paste0("left_", 1:3, "_measure")
curr_logic <- df$laterality == "right"
df[aff_cols] <- ifelse(replicate(3, curr_logic),
as.matrix(df[right_cols]),
as.matrix(df[left_cols]))
df
我是 R 的新手,我正在尝试在我的数据集中创建一个新的 columns/variables,df
,使用来自我的数据集中已经存在的多个列的信息。我希望使用 mapply
函数来执行此操作。这是指在某人的右侧和左侧进行的某些测量的数据。然而,这些方面中只有一个受到影响,并且由 df$laterality
定义。最终,我想创建新的 variable/columns,它将从测量中收集的数据定义为从受影响的一侧收集的数据。
我的数据,经过简化,基本上如下所示
recordID <- c(1, 2, 3, 4)
laterality <- c(right, right, left, right)
right_1_measure <- c(2.3, 3.4, 1.7, 2.4)
right_2_measure <- c(1.3, 2.2, 3.1, 4.1)
right_3_measure <- c(2.7, 2.8, 4.2, 3.9)
left_1_measure <- c(1.5, 2.6, 4.5, 2.8)
left_2_measure <- c(1.1, 3.4, 3.5, 2.6)
left_3_measure <- c (2.6, 2.8, 3.6, 1.6)
df <- data.frame(recordID, laterality, right_1_measure, right_2_measure, right_3_measure, left_1_measure, left_2_measure, left_3_measure)
然后我创建了一个列名称的向量,我希望循环通过它来创建新的“受影响的”variable/columns,我将根据之前定义的变量命名,但添加前缀“aff” .我还创建了一个包含我希望赋予新列的名称的向量。
right_vars <- c("right_1_measure", "right_2_measure" , "right_3_measure")
left_vars <- c("left_1_measure", "left_2_measure" , "left_3_measure")
aff_vars <- c("aff_1_measure", "aff_2_measure", "aff_3_measure")
然后我创建了我计划用来根据 df$laterality
aff_var_create <- function (x, y, z){
df$x <- ifelse(df$laterality == "Right" , df$y, ifelse (df$laterality == "Left", df$z, NA))
}
然后我创建了我的 mapply
代码
mapply(FUN = aff_var_create, x = aff_vars, y = r_vars, z = l_vars)
但是,当我 运行 这样做时,我收到以下错误消息:
Error in ans[ypos] <- rep(yes, length.out = len)[ypos] :
replacement has length zero
In addition: Warning message:
In rep(yes, length.out = len) :
Error in ans[ypos] <- rep(yes, length.out = len)[ypos] :
replacement has length zero
我检查了我的数据框,所有列中都有数据,所以我很困惑为什么 y.pos 的长度为零。
最终,我希望我的数据框如下所示
recordID <- c(1, 2, 3, 4)
laterality <- c(right, right, left, right)
right_1_measure <- c(2.3, 3.4, 1.7, 2.4)
right_2_measure <- c(1.3, 2.2, 3.1, 4.1)
right_3_measure <- c(2.7, 2.8, 4.2, 3.9)
left_1_measure <- c(1.5, 2.6, 4.5, 2.8)
left_2_measure <- c(1.1, 3.4, 3.5, 2.6)
left_3_measure <- c (2.6, 2.8, 3.6, 1.6)
aff_1_measure <- c(2.3, 3.4, 4.5, 2.4)
aff_2_measure <- c(1.3, 2.2, 3.5, 4.1)
aff_3_measure <- c(2.7, 2.8, 3.6, 3.9)
df <- data.frame(recordID, laterality, right_1_measure, right_2_measure, right_3_measure, left_1_measure, left_2_measure, left_3_measure, aff_1_measure, aff_2_measure, aff_3_measure)
如有任何解决此问题或使用其他方法获得类似结果的建议,我们将不胜感激!谢谢。
这不是 mapply
解决方案,但对于此类数据工作,我建议使用 tidyverse
包或至少其中的一部分:
library(dplyr)
library(tidyr)
df %>%
pivot_longer(matches("_\d+_measure"), names_to=c("side", "no"), names_pattern="(\w+)_(\d+)_measure") %>%
filter(laterality == side) %>%
select(-side) %>%
pivot_wider(names_from=no, names_glue="aff_{no}_measure") %>%
full_join(df, by=c("recordID", "laterality"))
哪个returns
# A tibble: 4 x 11
recordID laterality aff_1_measure aff_2_measure aff_3_measure right_1_measure right_2_measure right_3_measure
<dbl> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 right 2.3 1.3 2.7 2.3 1.3 2.7
2 2 right 3.4 2.2 2.8 3.4 2.2 2.8
3 3 left 4.5 3.5 3.6 1.7 3.1 4.2
4 4 right 2.4 4.1 3.9 2.4 4.1 3.9
# ... with 3 more variables: left_1_measure <dbl>, left_2_measure <dbl>, left_3_measure <dbl>
注意:您可以轻松更改列的顺序,使此输出与您想要的输出匹配。
我做了什么?
- 首先,我们使用
pivot_longer
将数据转换为“长”格式。这使我们能够过滤数据以获得正确的偏侧性。 - 现在我们必须采取措施使用
pivot_wider
创建aff_n_measure
列。 - 最后,我们使用
full_join
. 将这些新数据与您的旧数据结合起来
您不能使用 $
表示法动态传递字符串值。而是使用 [[
。此外,由于 mapply
不会就地更新数据框,您需要将结果分配给列:
right_vars <- c("right_1_measure", "right_2_measure" , "right_3_measure")
left_vars <- c("left_1_measure", "left_2_measure" , "left_3_measure")
aff_vars <- c("aff_1_measure", "aff_2_measure", "aff_3_measure")
aff_var_create <- function(x, y, z){
ifelse(df$laterality == "right" , df[[y]], ifelse(df$laterality == "left", df[[z]], NA))
}
df[aff_vars] <- mapply(FUN=aff_var_create, x=aff_vars, y=right_vars, z=left_vars)
df
或者,通过使用 [
的索引进行分配。
aff_cols <- paste0("aff_", 1:3, "_measure")
right_cols <- paste0("right_", 1:3, "_measure")
left_cols <- paste0("left_", 1:3, "_measure")
curr_logic <- df$laterality == "right"
# INITIALIZE COLUMNS
df[aff_cols] <- NA
# UPDATE COLUMNS BY INDEX
df[curr_logic , aff_cols] <- df[curr_logic , right_cols]
df[!curr_logic , aff_cols] <- df[!curr_logic, left_cols]
df
更好的是,使用单个 ifelse
调用,因为它可以 运行 向量和矩阵比较对齐到相同的维度(因此,replicate
)。
aff_cols <- paste0("aff_", 1:3, "_measure")
right_cols <- paste0("right_", 1:3, "_measure")
left_cols <- paste0("left_", 1:3, "_measure")
curr_logic <- df$laterality == "right"
df[aff_cols] <- ifelse(replicate(3, curr_logic),
as.matrix(df[right_cols]),
as.matrix(df[left_cols]))
df