【问题标题】:R - Subset based on conditions for paired dataR - 基于配对数据条件的子集
【发布时间】:2015-07-17 19:30:45
【问题描述】:

我正在尝试根据条件对配对数据进行子集化。
pair 包括在 2 天内观察到的两个个体。

我的样本的主要数据是: 'hldid', 'cid', 'pid', 'diary', 'sex', 'day', 'main1'

'hldid'指配对数据标识符,

'cid' 是配对的数据日标识符

'pid' 个人标识符 'diary'日记(每人必须填写2本日记) 'sex' 'day' 'main1' 指性别、日期和观察到的活动。

我想做的是根据 2 个条件对数据进行子集化:

  1. 数据必须配对,这意味着hldid 必须属于 2 个人。 每一对都应该由一男一女组成。
  2. 个人必须填写 2 个diary。所以hldid的4日记

我发现这样做的唯一方法是执行以下操作:

按性别区分

M = filter(dtaSimple, sex == 1)
W = filter(dtaSimple, sex == 2)

按配对日标识符合并

dtaSimple_c = merge(M, W, by = 'cid', suffixes = c('_m', '_w'))

那我就来了

     cid hldid_m  pid_m diary_m sex_m day_m main1_m hldid_w  pid_w diary_w sex_w day_w main1_w
 1 1250_1    1250 1250_2       1     1     1       0    1250 1250_1       1     2     1       0
 2 1250_2    1250 1250_2       2     1     3       0    1250 1250_1       2     2     3       0
 3 1294_1    1294 1294_2       1     1     6       0    1294 1294_1       1     2     6       0
 4 1294_2    1294 1294_2       2     1     1       0    1294 1294_1       2     2     1       0

我认为这并不令人满意。 每行指的是每个hldid 的第一条日记,每列指的是pair 的男人或女人。

我想保留 1 行 1 个人 1 天的原始数据结构。

   hldid    cid    pid diary sex day main1
1   1250 1250_1 1250_1     1   2   1     0
2   1250 1250_2 1250_1     2   2   3     0
3   1250 1250_1 1250_2     1   1   1     0
4   1250 1250_2 1250_2     2   1   3     0
 .....

数据:

dtaSimple = structure(
   list(
       hldid = c(1250, 1250, 1250, 1250, 1294, 1294, 1294, 1294, 1352, 1352), 
       cid = c("1250_1", "1250_2", "1250_1", "1250_2", "1294_1",  "1294_2", "1294_1", "1294_2", "1352_1", "1352_2"), 
       pid = c("1250_1", "1250_1", "1250_2", "1250_2", "1294_1", "1294_1", "1294_2", "1294_2", "1352_1", "1352_1"), 
       diary = c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L, 1L, 2L), 
       sex = c(2L, 2L, 1L, 1L, 2L, 2L, 1L, 1L, 2L, 2L), 
       day = c(1L, 3L, 1L, 3L, 6L, 1L, 6L, 1L, 1L, 3L), 
       main1 = c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L)), 
   .Names = c("hldid", "cid", "pid", "diary", "sex", "day", "main1"), 
   row.names = c(NA, 10L), 
   class = "data.frame"
)

【问题讨论】:

    标签: r merge subset


    【解决方案1】:

    听起来您需要按分组变量进行过滤。据我了解,对于每个 hldid,您要确保 sex 有 2 个不同的值,总共有 4 个观察值。

    您可以使用 dplyr 中的 filtergroup_by

    library(dplyr)
    
    dtaSimple %>% 
        group_by(hldid) %>%
        filter(n_distinct(sex) == 2, n() >= 4)
    
      hldid    cid    pid diary sex day main1
    1  1250 1250_1 1250_1     1   2   1     0
    2  1250 1250_2 1250_1     2   2   3     0
    3  1250 1250_1 1250_2     1   1   1     0
    4  1250 1250_2 1250_2     2   1   3     0
    5  1294 1294_1 1294_1     1   2   6     0
    6  1294 1294_2 1294_1     2   2   1     0
    7  1294 1294_1 1294_2     1   1   6     0
    8  1294 1294_2 1294_2     2   1   1     0
    

    更改数据集,使hldid 没有 4 个观察值来进行更彻底的测试:

    dtaSimple2 = dtaSimple[-4,]
    
    dtaSimple2 %>% 
        group_by(hldid) %>%
        filter(n_distinct(sex) == 2, n() >= 4)
    
      hldid    cid    pid diary sex day main1
    1  1294 1294_1 1294_1     1   2   6     0
    2  1294 1294_2 1294_1     2   2   1     0
    3  1294 1294_1 1294_2     1   1   6     0
    4  1294 1294_2 1294_2     2   1   1     0
    

    如果每个sex 必须有 2 个日记条目,并且一个性别可能有 1 个条目,而另一个性别可能有 3 个条目,则您需要稍微不同的策略。也许只是确保每个sex 对每个id 有两个以上的观察?

    dtaSimple %>% 
        group_by(hldid) %>%
        filter(sum(sex == 1) >= 2, sum(sex == 2) >= 2)
    

    【讨论】:

    • 好的,就在我掌握了ddply 的窍门后,我开始了解 dplyr 过滤。 R 太酷了!
    【解决方案2】:

    plyr 库中有一个函数ddply 有利于通过列值的组合进行快速分组和制表。考虑到您想要非常具体的分组计数,我喜欢ddply。这将两个ddply() 函数链接在一起,最终根据以下条件过滤掉个人: 1) 他们没有两个日记值

    # calculate the number of diaries by pid (we are looking for exactly two):
    diaryByPid <- ddply(dtaSimple,c("pid"),function(x){ length(unique(x$diary))})
    
    # the valid pids have exactly two unique diary values
    validPid <- diaryByPid$pid[which(diaryByPid[,2]==2)]
    
    # now subset the original dtaSimple to retain only those matched above
    dtaSub <- dtaSimple[which(dtaSimple$pid %in% validPid),]
    

    我们根据 pid 排除了没有两个唯一日记值的记录。现在我们需要将它们与对应的cid 值配对,并确保代表两种性别:

    # ddply to group by cid and count the number of unique values of $sex column
    sexByCid <- ddply(dtaSub,c("cid"),function(x){ length(unique(x$sex))})
    
    # retain the cids for which we have two unique sexes
    validCid <- sexByCid$cid[which(sexByCid[,2]==2)]
    
    # subset the previously subsetted dtaSub to remove records without gender matches.
    dtaSub2 <- dtaSub[which(dtaSub$cid %in% validCid),]
    

    因为我们只从原始结构中删除了行,所以它保持相同的格式:

    head(dtaSub2)
      hldid    cid    pid diary sex day main1
    1  1250 1250_1 1250_1     1   2   1     0
    2  1250 1250_2 1250_1     2   2   3     0
    3  1250 1250_1 1250_2     1   1   1     0
    4  1250 1250_2 1250_2     2   1   3     0
    5  1294 1294_1 1294_1     1   2   6     0
    6  1294 1294_2 1294_1     2   2   1     0
    7  1294 1294_1 1294_2     1   1   6     0
    8  1294 1294_2 1294_2     2   1   1     0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-23
      • 2019-06-01
      • 2022-08-18
      • 2019-10-22
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 2020-10-23
      相关资源
      最近更新 更多