根据R中的条件进行循环和连接

时间:2019-11-26 17:09:42

标签: r loops string-concatenation

我是R的新手,仍然在循环中挣扎。

我正在尝试创建一个循环,在该循环中,基于条件(variable_4 == 1),它将连接变量_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_4等于1并且结果为大字符串(用逗号分隔)时,循环才会累积variable_5的内容。

enter image description here

该循环将仅将标志为1的代理的名称粘贴到新的var中。如果Flag_1 = 1,则将代理的名称粘贴到new_var中,如果不是,则忽略。如果flag_2 = 1,则将代理的名称连接到新变量中,并用逗号分隔,否则,请忽略...

2 个答案:

答案 0 :(得分:0)

在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

答案 1 :(得分:0)

您不需要为此使用循环。数据采用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的代理粘贴在一起。既然我们的变量包含在单个列中,这很容易。

最后,我们使用wide恢复为pivot_wider格式。我们还取消了对先前分组的数据的分组,然后将列重新排序为所需的格式。