2016-09-28 110 views
1

我有一些我通過RODBC從數據庫中提取的表格。第一個主鍵字段爲__ID計算一個數據幀列和其他數據幀的所有列之間的相交值的數量

dfA <- data.frame(
`__ID` = c("a1","a2","a3"), 
col=c(1,2,3), 
check.names = FALSE) 

    __ID col 
1 a1 1 
2 a2 2 
3 a3 3 

,第二個與_ID啓動外鍵的字段。

dfB <- data.frame(
"_ID0" = c("z1", "z2", "z3"), 
"_ID1" = c("a1", "b1", "c1"), 
`_ID2` = c("a1", "a2", "c1"), 
`_ID3` = c("a1", "a2", "a3"), 
check.names = FALSE ) 

    _ID0 _ID1 _ID2 _ID3 
1 z1 a1 a1 a1 
2 z2 b1 a2 a2 
3 z3 c1 c1 a3 

我想產生具有上面的兩個表的名稱和具有不同於所述第一表中的主鍵字段,並從其他表的外鍵字段之間的所有配對組合以下數據幀。對於每一對,它顯示名爲intersects的列中的相交值的數量。

matches <- data.frame(
pk_table = "dfA", 
pk=c("__ID", "__ID","__ID","__ID"), 
fk_table= c("dfB", "dfB","dfB","dfB"), 
fk=c("_ID0", "_ID1", "_ID2", "_ID3"), 
intersects=c(0, 1,2,3), 
check.names = FALSE) 

    pk_table pk fk_table fk intersects 
1  dfA __ID  dfB _ID0   0 
2  dfA __ID  dfB _ID1   1 
3  dfA __ID  dfB _ID2   2 
4  dfA __ID  dfB _ID3   3 

這裏有一個如何爲intersects列的一個值,可以計算的例子。返回值1是因爲__ID列有一個值也在_ID1中找到。

length(intersect(dfA$`__ID`, dfB$`_ID1`)) 

如何創建上面沒有循環?我將理想地希望有接受下列輸入的解決方案:

  • 表名和主鍵字段的列名
  • 所有附加數據結構(dfBdfC等)

的函數應該計算主鍵字段和所有其他數據結構中所有其他列的匹配。總的來說,我的數據庫在15個表中有700列。我的主鍵字段位於一個表格中,我想要統計此列中的值在所有15個表格的每個列中出現的次數(包括找到該表格的相同表格)。我不能假定外鍵列遵循特定的命名約定,但數據庫中的數據總量小於50MB,所以我不希望出現性能問題。

回答

1

這應該做的伎倆:

library(dplyr) 
library(tidyr) 

options(stringsAsFactors = F) 

dfA <- data.frame(
    `__ID` = c("a1","a2","a3"), 
    col=c(1,2,3), 
    check.names = FALSE) 

dfB <- data.frame(
    fk_table = c("dfB", "dfB","dfB"), #added a column with the table name 
    `_ID0` = c("z1", "z2", "z3"), 
    `_ID1` = c("a1", "b1", "c1"), 
    `_ID2` = c("a1", "a2", "c1"), 
    `_ID3` = c("a1", "a2", "a3"), 
    check.names = FALSE ) 

dfB%>% 
    # first we gather the dataframe to long, tidy format 
    gather(key = fk, value = value, `_ID0`:`_ID3`)%>% 

    # then we do a left join. 
    # this introduces NA's for values (e.g. c1) that are not in dfA 
    left_join(dfA, by = c("value" = "__ID"))%>% 

    # Now we group by fk name (e.g. _ID0) 
    group_by(fk_table, fk)%>% 

    # And we count how often the result is not NA 
    # an inner_join followed by counting the rows would be simpler 
    # but then you don't get zero values as in the example 
    summarise(intersects=sum(!is.na(col))) 

這將返回以下:

fk_table fk intersects 
1  dfB _ID0   0 
2  dfB _ID1   1 
3  dfB _ID2   2 
4  dfB _ID3   3 

唯一的區別是你沒有在最終結果的PK和pk_table列,但我猜添加這個並不難。

+0

嗨Jeroen,謝謝你看起來不錯!我打算增加額外的表格。我假設我應該在你寫的那個之後直接添加更多的left_join命令?有關如何加入我擁有的所有表格的想法?現在,所有的數據幀都存儲在單個列表對象中。我認爲即使添加多個表並且列名在所有表中都不唯一,您的答案仍然有效,對嗎?這就是'fk_table'列的目的。 – Bobby

+0

如果你想組合多個表,你可能想看看你能否根據它們的內容將表分成兩種類型。如果這是可能的,只需使用bind_rows()函數將類似的表粘貼到單個長表中將會更容易。然後在您創建的長表上執行連接。 –

相關問題