【问题标题】:Select a group of rows which uniquely identified by more than one columns选择一组由多个列唯一标识的行
【发布时间】:2014-04-18 19:16:26
【问题描述】:

目前我刚刚开始学习 R 统计语言,并面临一个我几天都无法解决的问题。希望你们能帮我一把。思路如下:

  • 我有一个名为 DF 的数据集,其中包含数十万条记录。数据集由 5 列组成,如下所示:DF
  • CityID 格式为 5 个字符,前 2 个字符是 ProvinceID,与其他 3 个字符组合以唯一标识每个城市。
  • 每个 House 都由 ProvinceID、CityID 和 House 的组合唯一标识。
  • Person 被格式化为 6 个字符,前 4 个是他们的房子,结合其他 2 个字符来唯一标识每个人

-这里是示例数据的生成代码:

ProvinceID<-c(10,10,10,20,20,20,30,30,40,40,40,40,50)
CityID<-c(10001,10001,10002,20001,20002,20002,30001,30001,40001,40001,40001,40001,50001)
House<-c(0001,0001,0001,0001,0001,0002,0001,0002,0001,0001,0001,0002,0001)
Person<-c(000101,000102,000101,000101,000101,000101,000101,000101,000101,000102,000103,000101,000101)
WorkingStatus<-c(1,0,0,0,1,1,0,0,1,1,0,0,1)
DF<-cbind(ProvinceID,CityID,House,Person,WorkingStatus)

DF <-as.data.frame(DF)

我的问题是,创建一个名为“HouseIncome”的变量,如果至少一名家庭成员当前正在工作,则该变量的值为“1”(至少一名“人”的房子有 WorkingStatus ==1) .由于每个 House 只有在我们组合 3 列时才相同:“ProvinceID”、“CityID”和“House”,我只是想知道是否有任何方法将数据子集到房屋中,R 中是否有任何函数可以执行“如果至少”?

结果应如下所示:

ProvinceID<-c(10,10,20,20,20,30,30,40,40,50)
CityID<-c(10001,10002,20001,20002,20002,30001,30001,40001,40001,50001)
House<-c(0001,0001,0001,0001,0002,0001,0002,0001,0002,0001)
HouseIncome<-c(1,0,0,1,1,0,0,1,0,1)

DF1<-cbind(ProvinceID,CityID,House,HouseIncome)

【问题讨论】:

    标签: r unique subset


    【解决方案1】:

    这很容易使用data.table 包:

    library(data.table)
    dt <-data.table(DF) # your DF
    setkeyv(dt, c( "ProvinceID", "CityID", "House") )
    
    dt[, list(HouseIncome = as.integer(sum(WorkingStatus)>0)), by=key(dt)]
    
    
       ProvinceID CityID House HouseIncome
     1:         10  10001     1           1
     2:         10  10002     1           0
     3:         20  20001     1           0
     4:         20  20002     1           1
     5:         20  20002     2           1
     6:         30  30001     1           0
     7:         30  30001     2           0
     8:         40  40001     1           1
     9:         40  40001     2           0
    10:         50  50001     1           1
    

    @ChristianBorck 的回答非常好,+1。只是一些关于进一步改进它的提示。

    setDT(DF)[, list(HouseIncome = any(WorkingStatus == 1L)*1L), 
                        by=list(ProvinceID, CityID, House)]
    

    1) 您可以使用setDT 代替as.data.table(.)data.table(.),这将通过引用(无需复制)将您的data.frame 转换为data.table,从而避免不必要的内存使用,因此也是即时的.

    2) 而且,您可以,但不必使用 setkey 进行聚合/分组,除非您真的想对数据进行排序。

    【讨论】:

    • 很好,我不知道setDT。谢谢
    【解决方案2】:

    使用 plyr 包(或任何提供拆分-应用-组合功能的函数)非常简单:

    library(plyr)
    ddply(DF, .(ProvinceID, CityID, House), 
            summarise, HouseIncome=as.numeric(any(WorkingStatus==1)))
    #    ProvinceID CityID House HouseIncome
    # 1          10  10001     1           1
    # 2          10  10002     1           0
    # 3          20  20001     1           0
    # 4          20  20002     1           1
    # 5          20  20002     2           1
    # 6          30  30001     1           0
    # 7          30  30001     2           0
    # 8          40  40001     1           1
    # 9          40  40001     2           0
    # 10         50  50001     1           1
    

    【讨论】:

      【解决方案3】:

      要完成这一系列,这里有一个 dplyr 的答案。首先,我将创建 数据更安全的方式 - 你不应该使用cbind() 来制作数据框 因为它将所有输入强制为同一类型:

      df <- data.frame(
        ProvinceID = c(10, 10, 10, 20, 20, 20, 30, 30, 40, 40, 40, 40, 50),
        CityID = c(10001, 10001, 10002, 20001, 20002, 20002, 30001, 30001, 40001, 40001, 40001, 40001, 50001),
        House = c(0001, 0001, 0001, 0001, 0001, 0002, 0001, 0002, 0001, 0001, 0001, 0002, 0001),
        Person = c(000101, 000102, 000101, 000101, 000101, 000101, 000101, 000101, 000101, 000102, 000103, 000101, 000101),
        WorkingStatus = c(1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1)
      )
      

      使用 dplyr,您可以使用 group_by() 设置分组,并使用 mutate() 添加新列。我认为您最好将变量保留为 逻辑向量,而不是将其转换为 0/1。

      library(dplyr)
      df %.% 
        group_by(ProvinceID, CityID, House) %.%
        mutate(HouseIncome = any(WorkingStatus == 1))
      #> Source: local data frame [13 x 6]
      #> Groups: ProvinceID, CityID, House
      #> 
      #>    ProvinceID CityID House Person WorkingStatus HouseIncome
      #> 1          10  10001     1    101             1        TRUE
      #> 2          10  10001     1    102             0        TRUE
      #> 3          10  10002     1    101             0       FALSE
      #> 4          20  20001     1    101             0       FALSE
      #> 5          20  20002     1    101             1        TRUE
      #> 6          20  20002     2    101             1        TRUE
      #> 7          30  30001     1    101             0       FALSE
      #> 8          30  30001     2    101             0       FALSE
      #> 9          40  40001     1    101             1        TRUE
      #> 10         40  40001     1    102             1        TRUE
      #> 11         40  40001     1    103             0        TRUE
      #> 12         40  40001     2    101             0       FALSE
      #> 13         50  50001     1    101             1        TRUE
      

      【讨论】:

        【解决方案4】:

        可能是这样的,它将返回 True/False 结果而不是您想要的 1/0 -

        library(data.table) ## >= 1.9.2
        setDT(DF)[, list(HouseIncome = sum(WorkingStatus) > 0), 
                               by = list(ProvinceID,CityID,House)]
        
        #    ProvinceID CityID House HouseIncome
        #  1:         10  10001     1       FALSE
        #  2:         10  10002     1       FALSE
        #  3:         20  20001     1       FALSE
        #  4:         20  20002     1       FALSE
        #  5:         20  20002     2       FALSE
        #  6:         30  30001     1       FALSE
        #  7:         30  30001     2       FALSE
        #  8:         40  40001     1        TRUE
        #  9:         40  40001     2       FALSE
        # 10:         50  50001     1       FALSE
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-30
          相关资源
          最近更新 更多