基于R中的条件循环和连接
Looping and concatenating based on a condition in R
我是 R 的新手,仍在为循环而苦苦挣扎。
我正在尝试创建一个循环,根据条件 (variable_4 == 1),它将连接 variable_5 的内容,用逗号分隔。
data1 <- data.frame(
ID = c(123:127),
agent_1 = c('James', 'Lucas','Yousef', 'Kyle', 'Marisa'),
agent_2 = c('Sophie', 'Danielle', 'Noah', 'Alex', 'Marcus'),
agent_3 = c('Justine', 'Adrienne', 'Olivia', 'Janice', 'Josephine'),
Flag_1 = c(1,0,1,0,1),
Flag_2 = c(0,1,0,0,1),
Flag_3 = c(1,0,1,0,1)
)
data1$new_var<- ""
for(i in 2:10){
variable_4 <- paste0("flag_", i)
variable_5 <- paste0("agent_", i)
data1 <- data1 %>%
mutate(!! new_var = case_when(variable_4 == 1,paste(new_var, variable_5, sep=",")))
}
我在前面的步骤中创建了 new_var,因为代码给我一个错误,指出找不到变量。理想情况下,循环将累加 variable_5 的内容,仅当 variable_4 等于 1 并且结果将是大字符串,以逗号分隔。
循环将仅在新变量中粘贴标志为 = 1 的代理名称。如果 Flag_1=1,则在 new_var 中粘贴代理名称,如果没有,请忽略。如果flag_2 =1,则在新var中连接agent的名字,用逗号分隔,如果不是,则忽略...
在 BaseR 或 tidyverse 或两者的组合中有几种不同的方法可以做到这一点,如果你坚持使用 tidyverse 那么考虑一下这个:
我已经使用 mtcars 作为你的数据框了!
#load dplyr or tidyverse
library(tidyverse)
# create data as mtcars
df <- mtcars
# create two new columns flag and agent as rownumbers
df <- df %>%
mutate(flag = paste0("flag", row_number())) %>%
mutate(agent = paste0("agent", row_number()))
# using case when in mutate statement
df2 <- df %>%
mutate(new_column = ifelse(flag == "flag1", yes = paste0(agent, " this is a new variable"), no = flag))
print(df2)
如果您有一个案例,则 ifelse 语句可能更合适 - 但如果您有多个案例,则改用 case_when
。
您不需要为此使用循环。数据采用 wide
格式,这使得它更难,但如果我们转换为 long
格式,我们可以轻松找到矢量化解决方案而不是使用循环。
pivot_longer
函数在这里很有用,需要tidyr
版本>=1.0.0.
library(tidyr)
library(dplyr)
pivot_longer(data1,
cols = -ID,
names_to = c(".value", "group"),
names_sep = "_") %>%
group_by(ID) %>%
mutate(new_var = paste0(agent[Flag==1], collapse = ',')) %>%
pivot_wider(names_from = c("group"),
values_from = c('agent', 'Flag'),
names_sep = '_') %>%
ungroup() %>%
select(ID, starts_with('agent'), starts_with('Flag'), new_var)
## A tibble: 5 x 8
# ID agent_1 agent_2 agent_3 Flag_1 Flag_2 Flag_3 new_var
# <int> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#1 123 James Sophie Justine 1 0 1 James,Justine
#2 124 Lucas Danielle Adrienne 0 1 0 Danielle
#3 125 Yousef Noah Olivia 1 0 1 Yousef,Olivia
#4 126 Kyle Alex Janice 0 0 0 ""
#5 127 Marisa Marcus Josephine 1 1 1 Marisa,Marcus,Josephine
详情:
pivot_longer
将我们的数据置于更自然的格式中,其中每一行代表对变量 agent 和 flag 的一个观察,而不是多个:
pivot_longer(data1,
cols = -ID,
names_to = c(".value", "group"),
names_sep = "_")
## A tibble: 15 x 4
# ID group agent Flag
# <int> <chr> <chr> <chr>
# 1 123 1 James 1
# 2 123 2 Sophie 0
# 3 123 3 Justine 1
# 4 124 1 Lucas 0
# 5 124 2 Danielle 1
# 6 124 3 Adrienne 0
# ...
对于每个 ID,我们可以将标志值为 1 的代理粘贴在一起。现在这很容易,因为我们的变量包含在单个列中。
最后,我们使用 pivot_wider
恢复到 wide
格式。我们还取消了之前分组的数据,并将列重新排序为所需格式。
我是 R 的新手,仍在为循环而苦苦挣扎。
我正在尝试创建一个循环,根据条件 (variable_4 == 1),它将连接 variable_5 的内容,用逗号分隔。
data1 <- data.frame(
ID = c(123:127),
agent_1 = c('James', 'Lucas','Yousef', 'Kyle', 'Marisa'),
agent_2 = c('Sophie', 'Danielle', 'Noah', 'Alex', 'Marcus'),
agent_3 = c('Justine', 'Adrienne', 'Olivia', 'Janice', 'Josephine'),
Flag_1 = c(1,0,1,0,1),
Flag_2 = c(0,1,0,0,1),
Flag_3 = c(1,0,1,0,1)
)
data1$new_var<- ""
for(i in 2:10){
variable_4 <- paste0("flag_", i)
variable_5 <- paste0("agent_", i)
data1 <- data1 %>%
mutate(!! new_var = case_when(variable_4 == 1,paste(new_var, variable_5, sep=",")))
}
我在前面的步骤中创建了 new_var,因为代码给我一个错误,指出找不到变量。理想情况下,循环将累加 variable_5 的内容,仅当 variable_4 等于 1 并且结果将是大字符串,以逗号分隔。
循环将仅在新变量中粘贴标志为 = 1 的代理名称。如果 Flag_1=1,则在 new_var 中粘贴代理名称,如果没有,请忽略。如果flag_2 =1,则在新var中连接agent的名字,用逗号分隔,如果不是,则忽略...
在 BaseR 或 tidyverse 或两者的组合中有几种不同的方法可以做到这一点,如果你坚持使用 tidyverse 那么考虑一下这个:
我已经使用 mtcars 作为你的数据框了!
#load dplyr or tidyverse
library(tidyverse)
# create data as mtcars
df <- mtcars
# create two new columns flag and agent as rownumbers
df <- df %>%
mutate(flag = paste0("flag", row_number())) %>%
mutate(agent = paste0("agent", row_number()))
# using case when in mutate statement
df2 <- df %>%
mutate(new_column = ifelse(flag == "flag1", yes = paste0(agent, " this is a new variable"), no = flag))
print(df2)
如果您有一个案例,则 ifelse 语句可能更合适 - 但如果您有多个案例,则改用 case_when
。
您不需要为此使用循环。数据采用 wide
格式,这使得它更难,但如果我们转换为 long
格式,我们可以轻松找到矢量化解决方案而不是使用循环。
pivot_longer
函数在这里很有用,需要tidyr
版本>=1.0.0.
library(tidyr)
library(dplyr)
pivot_longer(data1,
cols = -ID,
names_to = c(".value", "group"),
names_sep = "_") %>%
group_by(ID) %>%
mutate(new_var = paste0(agent[Flag==1], collapse = ',')) %>%
pivot_wider(names_from = c("group"),
values_from = c('agent', 'Flag'),
names_sep = '_') %>%
ungroup() %>%
select(ID, starts_with('agent'), starts_with('Flag'), new_var)
## A tibble: 5 x 8
# ID agent_1 agent_2 agent_3 Flag_1 Flag_2 Flag_3 new_var
# <int> <chr> <chr> <chr> <chr> <chr> <chr> <chr>
#1 123 James Sophie Justine 1 0 1 James,Justine
#2 124 Lucas Danielle Adrienne 0 1 0 Danielle
#3 125 Yousef Noah Olivia 1 0 1 Yousef,Olivia
#4 126 Kyle Alex Janice 0 0 0 ""
#5 127 Marisa Marcus Josephine 1 1 1 Marisa,Marcus,Josephine
详情:
pivot_longer
将我们的数据置于更自然的格式中,其中每一行代表对变量 agent 和 flag 的一个观察,而不是多个:
pivot_longer(data1,
cols = -ID,
names_to = c(".value", "group"),
names_sep = "_")
## A tibble: 15 x 4
# ID group agent Flag
# <int> <chr> <chr> <chr>
# 1 123 1 James 1
# 2 123 2 Sophie 0
# 3 123 3 Justine 1
# 4 124 1 Lucas 0
# 5 124 2 Danielle 1
# 6 124 3 Adrienne 0
# ...
对于每个 ID,我们可以将标志值为 1 的代理粘贴在一起。现在这很容易,因为我们的变量包含在单个列中。
最后,我们使用 pivot_wider
恢复到 wide
格式。我们还取消了之前分组的数据,并将列重新排序为所需格式。