2015-03-02 67 views
1

下午聰明的人。R - 基於匹配到列名的設置值

我有一個體面的大小的數據集(> 800k行),作爲一個例子,我已經拉出了20行2列的小樣本。首先,只有「主題」列填充了一個矢量,其他所有列都設置爲FALSE。

因爲它位於當前這將重新創建數據...

Topics <- c("E11,E31,E313,ECAT" , "E1,E20") 
    E1  <- c(FALSE, FALSE) 
    E11 <- c(FALSE, FALSE) 
    E20 <- c(FALSE, FALSE) 
    E30 <- c(FALSE, FALSE) 
    E31 <- c(FALSE, FALSE) 
    E100 <- c(FALSE, FALSE) 
    E300 <- c(FALSE, FALSE) 
    E313 <- c(FALSE, FALSE) 
    ECAT <- c(FALSE, FALSE) 
    df  <- data.frame(Topics,E1,E11,E20,E30,E31,E100,E300,E313,ECAT) 

哪位能給像...

Topics    E1 E11 E20 E30 E31 E100 E300 E313 ECAT 
E11,E31,E313,ECAT FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 
E1,E20    FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

我想設置相關的行,列TRUE其中,主題向量中的每個項目都有匹配。因此,它應該是這個樣子......

Topics    E1 E11 E20 E30 E31 E100 E300 E313 ECAT 
E11,E31,E313,ECAT FALSE TRUE FALSE FALSE TRUE FALSE TRUE FALSE TRUE 
E1,E20    TRUE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE 

到目前爲止,我已經完全失敗的工作這一個,但我懷疑它是這樣的:

  • 分裂成話題用strsplit
  • 矢量
  • 爲載體的每一項嘗試匹配names(df)
  • 當組匹配的行,列== TRUE

但是我嘗試過各種各樣,無法理解邏輯。任何人都可以爲我分解這件事嗎?

+1

在預期的結果中,'E313'應該是'TRUE'而不是'E300' – akrun 2015-03-02 17:26:15

回答

1

嘗試

df[-1] <- t(vapply(strsplit(as.character(df$Topics), ','), 
       function(x) names(df)[-1] %in% x, logical(ncol(df)-1))) 
df 
#    Topics E1 E11 E20 E30 E31 E100 E300 E313 ECAT 
#1 E11,E31,E313,ECAT FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE TRUE 
#2   E1,E20 TRUE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE 

或者

df[-1] <- t(vapply(strsplit(as.character(df$Topics), ","), function(x) 
     !!table(factor(x, levels=names(df)[-1])), logical(ncol(df)-1))) 
+0

史詩。所以我花了一整天的時間,並可能放下50-60行代碼試圖讓這個工作..你在一個!傑出的,只是去顯示多少進一步我必須與R.乾杯。 – BarneyC 2015-03-02 18:04:02

+0

@BarneyC很高興幫助你。這只是基於經驗。 – akrun 2015-03-02 18:14:10

+0

我可以問,如果在「主題」之前有另一列,我會改變什麼?我想我在問什麼-1指標的含義以及我將它們設置爲什麼。乾杯 – BarneyC 2015-03-02 18:18:41

1

這裏幾乎是一步一步的方法來邏輯你描述:

## make note of the column names 
Colnames <- names(df[-1]) 

## Create an empty FALSE matrix to modify later 
Mat <- matrix(FALSE, nrow = nrow(df), 
       ncol = length(Colnames), 
       dimnames = list(NULL, Colnames)) 

## Use strsplit to split the "Topics" column 
L <- strsplit(as.character(df[[1]]), ",", fixed = TRUE) 

## Figure out which values match with which columns 
## I'm using matrix indexing here to set those values to TRUE 
Mat[cbind(rep(seq_along(L), vapply(L, length, 1L)), 
      match(unlist(L), Colnames))] <- TRUE 

## Replacement in the original dataset 
df[-1] <- Mat 
df 
#    Topics E1 E11 E20 E30 E31 E100 E300 E313 ECAT 
# 1 E11,E31,E313,ECAT FALSE TRUE FALSE FALSE TRUE FALSE FALSE TRUE TRUE 
# 2   E1,E20 TRUE FALSE TRUE FALSE FALSE FALSE FALSE FALSE FALSE 

如果你剛剛開始與「主題」欄,這裏是幾個自變量附件可以考慮:

  1. mtabulate從 「qdapTools」

    > library(qdapTools) 
    > mtabulate(strsplit(as.character(df$Topics), ",", TRUE)) 
        E1 E11 E20 E31 E313 ECAT 
    1 0 1 0 1 1 1 
    2 1 0 1 0 0 0 
    
  2. cSplit_e從我的 「splitstackshape」 包

    library(splitstackshape) 
    cSplit_e(df[1], "Topics", ",", type = "character", fill = 0) 
    #    Topics Topics_E1 Topics_E11 Topics_E20 Topics_E31 Topics_E313 Topics_ECAT 
    # 1 E11,E31,E313,ECAT   0   1   0   1   1   1 
    # 2   E1,E20   1   0   1   0   0   0 
    

雙方將需要額外的一點點努力確保您所期望的所有列都包含在內(an d將1和0轉換爲TRUEFALSE)。

+0

該演練非常棒,與我的想法完全吻合。感謝那。 – BarneyC 2015-03-02 18:03:09