2016-10-28 95 views
1

假設我有數據框,並且想要查看給定列中的每個給定值是否等於第二列的下一行中的值?跨列匹配值

我能爲1場做到這一點,但我想這樣做對整個數據幀:

match(dataset$co1[i], dataset$co1[i+1]) # where i is a given row # 

測試數據集:

case <- c("A", "B", "C", "A", "A", "A" ,"B", "C", "B", "A") 
col1 <- c(1, 100, 50, 600, 29, 72, 7, 64, 15, 85) 
col2 <- c(600, 7, 64, 29, 57, 85, 12, 82, 71, 34) 
dataset <- data.frame(case, col1, col2) 

我也想這樣做這個BY情況。我試圖看看我是否可以在比賽中發表聲明,但我很難弄清楚如何沿着一列進行索引。

有什麼建議嗎?

+1

我感到困惑的預期輸出爲例。在這裏沒有可以找到匹配的行,對吧? – Frank

+0

你的意思是說'匹配(數據集$ col1 [i],數據集$ col2 [i + 1])'對嗎? – useR

+0

如果您發現它有幫助,請不要忘記接受答案:) – useR

回答

0

正如@Frank指出的,根據您的匹配條件和您提供的數據集,不會有任何匹配。所以出於說明的目的,我修改了你的數據集以表明我的解決方案真的有效。這裏有一個簡單的方法使用dplyr:

# Modified dataset 
case <- c("A", "B", "C", "A", "A", "A" ,"B", "C", "B", "A") 
col1 <- c(1, 100, 50, 600, 29, 72, 7, 64, 15, 85) 
col2 <- c(600, 7, 64, 1, 600, 85, 100, 82, 71, 34) 
dataset <- data.frame(case, col1, col2) 
> dataset 
    case col1 col2 
1  A 1 600 
2  B 100 7 
3  C 50 64 
4  A 600 1 
5  A 29 600 
6  A 72 85 
7  B 7 100 
8  C 64 82 
9  B 15 71 
10 A 85 34 

請注意,我改變了COL2的第4行至1,第5行600和第7行100這樣COL2的第4行會配合1日當匹配時,col2的第5個與col1的第4個匹配,並且col2的第7個與col1的第2個匹配。此外,當不是大小寫匹配時,只有第5列col2將與col1的第4列匹配。

library(dplyr) 
dataset %>% 
    add_rownames() %>% 
    mutate(col2 = lead(col2)) %>% 
    filter(col1 == col2) 

# A tibble: 1 × 4 
    rowname case col1 col2 
    <chr> <fctr> <dbl> <dbl> 
1  4  A 600 600 

該代碼返回與col2的下一行匹配的col1的行。我加了add_rownames(),這樣你就知道它的原始行索引datasetmutate()中的lead()功能與dplyr中的lag()簡單相反(基數R中的通用lag()不允許延遲非時間序列向量)。它通過k = -1「落後」col2。

dataset %>% 
    add_rownames() %>% 
    group_by(case) %>% 
    mutate(col2 = lead(col2)) %>% 
    filter(col1 == col2) 

Source: local data frame [3 x 4] 
Groups: case [2] 

    rowname case col1 col2 
    <chr> <fctr> <dbl> <dbl> 
1  1  A  1  1 
2  2  B 100 100 
3  4  A 600 600 

通過添加group_by(),您可以做同樣的事情,但通過「案例」。如您所見,它會按照預期返回匹配的行。

如果你不想使用dplyr出於某種原因,這裏是一個更通用的解決方案:

## No group by case 
# Lag col2 (Call the lagged column col3) 
dataset$col3 = c(dataset$col2[-1], NA) 

dataset$match = mapply(function(x, y) match(x, y, nomatch = FALSE), 
         dataset$col1, dataset$col3) 

> dataset[dataset$match == 1,] 
    case col1 col2 col3 match 
4 A 600 1 600  1 

## Group by case 
# Split dataset into groups 
dataList = split(dataset, case) 

dataMatched = lapply(dataList, function(x){ 
    x$col2 = c(x$col2[-1], NA) 
    x$match = mapply(function(x, y) match(x, y, nomatch = FALSE), 
      x$col1, x$col2) 
    return(x) 
}) 

結果列表/數據幀:

> dataMatched 
$A 
    case col1 col2 match 
1  A 1 1  1 
4  A 600 600  1 
5  A 29 85  0 
6  A 72 34  0 
10 A 85 NA  0 

$B 
    case col1 col2 match 
2 B 100 100  1 
7 B 7 71  0 
9 B 15 NA  0 

$C 
    case col1 col2 match 
3 C 50 82  0 
8 C 64 NA  0 

> unsplit(dataMatched, case) 
    case col1 col2 match 
1  A 1 1  1 
2  B 100 100  1 
3  C 50 82  0 
4  A 600 600  1 
5  A 29 85  0 
6  A 72 34  0 
7  B 7 71  0 
8  C 64 NA  0 
9  B 15 NA  0 
10 A 85 NA  0