根据多个条件重塑数据框架

4

我希望能够在时间t内识别在同一地点和与同一人进行的活动。变量wher表示时间步骤,并记录了活动在时间t发生的地点。参数with记录了在时间t活动时的伴侣。我想根据性别知道在同一地点和与同一人进行的常见活动。我将不常见的活动以及在不同地方与不同人进行的活动替换为0。

输入

id     DMSex       t1  t2  t3  t4  wher1 wher2 wher3 wher4 wit1 wit2 wit3 wit4  
12       M         12  12  12  12  1        1   1     4     8     9    4    0  
12       F         10  13  12  12  3        1   1     5     6     5    4    1

输出:

id  t1  t2  t3  t4  
12   0   0  12  0  

18个时间步骤的示例数据:

structure(list(serial = c(11011202, 11011202), DMSex = c(1, 2
), act1_1 = c(110, 110), act1_2 = c(110, 110), act1_3 = c(110, 
110), act1_4 = c(110, 110), act1_5 = c(110, 110), act1_6 = c(110, 
110), act1_7 = c(110, 110), act1_8 = c(110, 110), act1_9 = c(110, 
110), act1_10 = c(110, 110), act1_11 = c(110, 110), act1_12 = c(8219, 
110), act1_13 = c(310, 110), act1_14 = c(3210, 110), act1_15 = c(3110, 
110), act1_16 = c(7241, 110), act1_17 = c(210, 110), act1_18 = c(3819, 
110), wher_1 = c(11, 11), wher_2 = c(11, 11), wher_3 = c(11, 
11), wher_4 = c(11, 11), wher_5 = c(11, 11), wher_6 = c(11, 11
), wher_7 = c(11, 11), wher_8 = c(11, 11), wher_9 = c(11, 11), 
    wher_10 = c(11, 11), wher_11 = c(11, 11), wher_12 = c(11, 
    11), wher_13 = c(11, 11), wher_14 = c(11, 11), wher_15 = c(11, 
    11), wher_16 = c(11, 11), wher_17 = c(11, 11), wher_18 = c(11, 
    11), wit4_1 = c(0, 0), wit4_2 = c(0, 0), wit4_3 = c(0, 0), 
    wit4_4 = c(0, 0), wit4_5 = c(0, 0), wit4_6 = c(0, 0), wit4_7 = c(0, 
    0), wit4_8 = c(0, 0), wit4_9 = c(0, 0), wit4_10 = c(0, 0), 
    wit4_11 = c(0, 0), wit4_12 = c(0, 0), wit4_13 = c(0, 0), 
    wit4_14 = c(0, 0), wit4_15 = c(0, 0), wit4_16 = c(0, 0), 
    wit4_17 = c(0, 0), wit4_18 = c(0, 0)), row.names = 1:2, class = "data.frame")

act1_twit4wit,而wher_wher

1个回答

2

结合 dplyrpurrr 的一种解决方案可能如下:

map(.x = as.character(1:4),
    ~ df %>%
     select(id, ends_with(.x)) %>%
     group_by(id) %>%
     mutate_at(vars(matches("^wher|^wit")), ~ all(. == first(.))) %>%
     ungroup() %>%
     mutate(cond = rowSums(select(.,  matches("^wher|^wit"))) == 2) %>%
     group_by(id) %>%
     mutate_at(vars(starts_with("t")), ~ all(. == first(.)) * cond * .) %>%
     ungroup() %>%
     select(starts_with("t"))) %>%
 bind_cols(df %>%
            select(id)) %>%
 group_by(id) %>%
 summarise_all(first)

     id    t1    t2    t3    t4
  <int> <int> <int> <int> <int>
1    12     0     0    12     0

首先,它从1到4创建一个字符向量,因为有四对变量(从t1,wher1,wit1到t4,wher4,wit4)。将映射函数应用于这些元素。其次,从df中单独选择变量对,并检查每个ID的所有行是否在wher和wit方面相同,从而创建一个逻辑条件。第三,它检查t变量在每个ID的所有行中是否相同,并将其与步骤2中的逻辑条件进行比较。如果为TRUE,则返回原始值;否则返回0。最后,它组合数据并保留每个ID的一行。
针对更新问题的解决方案,增加了stringr:
map(.x = str_extract(names(df)[grepl("^act", names(df))], "_.*+$"),
    ~ df %>%
     select(serial, ends_with(.x)) %>%
     group_by(serial) %>%
     mutate_at(vars(matches("^wher|^wit")), ~ all(. == first(.))) %>%
     ungroup() %>%
     mutate(cond = rowSums(select(.,  matches("^wher|^wit"))) == 2) %>%
     group_by(serial) %>%
     mutate_at(vars(starts_with("act")), ~ all(. == first(.)) * cond * .) %>%
     ungroup() %>%
     select(starts_with("act"))) %>%
 bind_cols(df %>%
            select(serial)) %>%
 group_by(serial) %>%
 summarise_all(first)

  serial act1_1 act1_2 act1_3 act1_4 act1_5 act1_6 act1_7 act1_8 act1_9 act1_10 act1_11 act1_12
   <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>   <dbl>   <dbl>   <dbl>
1 1.10e7    110    110    110    110    110    110    110    110    110     110     110       0
# … with 6 more variables: act1_13 <dbl>, act1_14 <dbl>, act1_15 <dbl>, act1_16 <dbl>,
#   act1_17 <dbl>, act1_18 <dbl>

提供一些解释 :) - tmfmnk
你的意思是输出结果不是按照 t1 到 t100 的顺序排列的吗? - tmfmnk
非常感谢您的时间,我的意思是,如果我使用指数运算符,我不会得到100个时间步长,我会得到更多,而我不知道如何减少这个数量。 - user11418708
请问您能否提供一些额外的样本数据?最好使用 dput() 函数。 - tmfmnk
我不得不将样本数据减少到18个时间步,因为数据太大了。 - user11418708
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接