R - соотношение между статьями в документе - PullRequest
2 голосов
/ 10 марта 2020

Я пытаюсь вычислить соотношение между статьями, чтобы получить представление о том, как часто разные номера статей появлялись вместе в документе (счет-фактура).

У меня есть запрос к таблице из SQL с двумя столбцами: Номер документа, Номер статьи Таблица довольно огромная с 21 тыс. Строк.

У меня есть 5k номеров документов и 700 различных статей, как показано ниже. Это фрейм данных "db_belege".

    Document Number Article Number
1   14198915        00115027
2   14198915        00100288
3   14198915        00011754
4   14198917        00033908
5   14198917        00096478
6   14198917        00033835
7   14198917        00051912
8   14198917        00152477
9   14198917        00033831
10  14198917        00100279
11  14198917        00011754
... 14198924        00053366
5k  14200000        00053366

Я собираюсь создать таблицу, в которой будут документы для строк и статьи для столбцов. Я подготовил для этого пустую матрицу с помощью следующего кода r:

#create distinct article list
db_dist_art <- dbFetch(dbSendQuery(conant, "SELECT DISTINCT [Artikelnummer] FROM documenttable WHERE conditions "))

#Number of aticles
dim(db_dist_art)[1]

#create distint document numbers list
db_dist_art <- dbFetch(dbSendQuery(conant, "SELECT DISTINCT [Belegnummer] FROM documenttable WHERE conditions "))

#Number of documents
dim(db_dist_bel)[1]

mat <- matrix(,dim(db_dist_bel)[1],dim(db_dist_art)[1])

В результате появится список запрошенных строк и столбцов.

1 / Как теперь я могу назвать столбцы и строки в соответствии с db_dist_art и db_dist_bel?

2 / Можно ли использовать обозначение строк и столбцов для распределения значений?

Моя цель состоит в том, чтобы я мог использовать функцию cor () .

3 / Или есть другой способ, который я не нашел в моем списке, который проще?

(пожалуйста, обратитесь к соответствующему решению, если доступно. Я новичок в этой теме c из-за исследования и не уверен, что я уже нашел правильные условия поиска, но я много искал, прежде чем задавать свой первый вопрос здесь.)

Мое решение на основе ответов


#First of all thank you very much for your awnser. the 2nd solution works without trouble. But i have issues to get the first one running below my adaption and results.
#straghtforward way from JBGruber

#Load/Install packages
library(DBI)
library(odbc)

#Establish connection
conant <- DBI::dbConnect(odbc::odbc(), 
                      Driver = "ODBC Driver 17 for SQL Server", 
                      Server = "Serveradress", 
                      Database = "databasename", 
                      encoding = "latin1",
                      Trusted_Connection = "yes")

#extract data for correlation

cordata <-  dbSendQuery(conant, "SELECT [Belegnummer] as 'Document_Number' ,[Artikelnummer] as 'Article_Number'  FROM tablename WHERE conditions ")
db_cordata <- dbFetch(cordata,)
dbClearResult(cordata)

#calculate correlation and store results in cor_result
library(tidyverse)
library(widyr)

cor_result <- db_cordata %>%
  pairwise_cor(Article_Number, Document_Number, upper = FALSE)


По-прежнему борются с матрицей корреляции и функцией cor ()


#to use cor():
#my adaption below, I had values 1 and "NULL" instead of NA so I adapted also the replace statement to the following below:

library(tidyverse)
mat <- db_cordata %>% 
  mutate(value = 1) %>% 
  pivot_wider(id_cols = Document_Number, names_from = Article_Number) %>%
  {
    mat <- as.matrix(.[, -1])
    rownames(mat) <- unlist(.[, 1])
    mat
  } %>% 
  replace(.,. == "NULL", 0)

# the matrix created seems to be correct. The values are 1 or 0 now. type duoble


#when i execute:
mat %>% 
  cor()

#it result in this issue
Fehler in cor(.) : 'x' must be numeric

#But double is numeric as far as i know. but the cor() return an error.
#a strange thing appear for me in this solution. When i hit mat in the Envirionment register > area "Data" this result in a View(mat) command in the console and display a List [50043 x 743]; List of length 3746949 and the valies are double[1] with 0 or 1
#by running the same command in console manually i receive the following: list[3746950] List of length 3746950 (so one more) with the values double[1] with 1 and NULL with Pairlist of length 0.
#why is it handled differently? I guess this is the reason for the issue with cor().

#when i just call 'mat' it display the matric correctly with 0 instead of "NULL".
mat

Интересно, если это ошибка R Studio.

Ответы [ 2 ]

1 голос
/ 10 марта 2020

Это то, с чего я бы начал для первых 11 строк.

Импорт данных

dfr <- read.table(text = "   Document_Number Article_Number
1   14198915        00115027
2   14198915        00100288
3   14198915        00011754
4   14198917        00033908
5   14198917        00096478
6   14198917        00033835
7   14198917        00051912
8   14198917        00152477
9   14198917        00033831
10  14198917        00100279
11  14198917        00011754")

dfr <- as.data.frame( lapply(dfr, as.character) , stringsAsFactors = FALSE)
str(dfr)
#> 'data.frame':    11 obs. of  2 variables:
#>  $ Document_Number: chr  "14198915" "14198915" "14198915" "14198917" ...
#>  $ Article_Number : chr  "115027" "100288" "11754" "33908" ...

Вычислите подсчет частоты

# --- count modalities
doc_table <- table(dfr)
doc_table
#>                Article_Number
#> Document_Number 100279 100288 115027 11754 152477 33831 33835 33908 51912 96478
#>        14198915      0      1      1     1      0     0     0     0     0     0
#>        14198917      1      0      0     1      1     1     1     1     1     1

Для сопоставления документов (или для поиска сходств)

cor(doc_table)
#> Warning in cor(doc_table): l'écart type est nulle
#>        100279 100288 115027 11754 152477 33831 33835 33908 51912 96478
#> 100279      1     -1     -1    NA      1     1     1     1     1     1
#> 100288     -1      1      1    NA     -1    -1    -1    -1    -1    -1
#> 115027     -1      1      1    NA     -1    -1    -1    -1    -1    -1
#> 11754      NA     NA     NA     1     NA    NA    NA    NA    NA    NA
#> 152477      1     -1     -1    NA      1     1     1     1     1     1
#> 33831       1     -1     -1    NA      1     1     1     1     1     1
#> 33835       1     -1     -1    NA      1     1     1     1     1     1
#> 33908       1     -1     -1    NA      1     1     1     1     1     1
#> 51912       1     -1     -1    NA      1     1     1     1     1     1
#> 96478       1     -1     -1    NA      1     1     1     1     1     1

Для сопоставления статей

cor(t(doc_table))
#>            14198915   14198917
#> 14198915  1.0000000 -0.7637626
#> 14198917 -0.7637626  1.0000000

Изучите некоторые, а именно для анализа корреспонденции здесь максимум один документ на статью, поэтому он не показывает много (только существующая корреспонденция).

# --- heat map ; get the number to dig in
library(ggplot2)
library(dplyr)
dfr %>% 
        as_tibble() %>% 
        group_by_all() %>% 
        summarise(nb = n()) %>% 
        ggplot(data = ., mapping = aes(x = Document_Number , y = Article_Number, fill = nb)) +
        geom_tile()

Наконец : вы должны проверить математические поля анализа корреспонденции и анализа текста , которые должны помочь вам в анализе вашего текста.

1 голос
/ 10 марта 2020

Если вы хотите привести данные в правильный формат для использования cor, мы можем использовать tidyr 'pivot_wider и затем преобразовать в матрицу:

library(tidyverse)
mat <- df %>% 
  mutate(value = 1) %>% 
  pivot_wider(id_cols = Document_Number, names_from = Article_Number) %>%
  {
    mat <- as.matrix(.[, -1])
    rownames(mat) <- unlist(.[, 1])
    mat
  } %>% 
  replace(is.na(.), 0)

mat %>% 
  cor()
#>            115027     100288      11754      33908      96478      33835
#> 115027  1.0000000  1.0000000  0.5773503 -0.3333333 -0.3333333 -0.3333333
#> 100288  1.0000000  1.0000000  0.5773503 -0.3333333 -0.3333333 -0.3333333
#> 11754   0.5773503  0.5773503  1.0000000  0.5773503  0.5773503  0.5773503
#> 33908  -0.3333333 -0.3333333  0.5773503  1.0000000  1.0000000  1.0000000
#> 96478  -0.3333333 -0.3333333  0.5773503  1.0000000  1.0000000  1.0000000
#> 33835  -0.3333333 -0.3333333  0.5773503  1.0000000  1.0000000  1.0000000
#> 51912  -0.3333333 -0.3333333  0.5773503  1.0000000  1.0000000  1.0000000
#> 152477 -0.3333333 -0.3333333  0.5773503  1.0000000  1.0000000  1.0000000
#> 33831  -0.3333333 -0.3333333  0.5773503  1.0000000  1.0000000  1.0000000
#> 100279 -0.3333333 -0.3333333  0.5773503  1.0000000  1.0000000  1.0000000
#> 53366  -0.5773503 -0.5773503 -1.0000000 -0.5773503 -0.5773503 -0.5773503
#>             51912     152477      33831     100279      53366
#> 115027 -0.3333333 -0.3333333 -0.3333333 -0.3333333 -0.5773503
#> 100288 -0.3333333 -0.3333333 -0.3333333 -0.3333333 -0.5773503
#> 11754   0.5773503  0.5773503  0.5773503  0.5773503 -1.0000000
#> 33908   1.0000000  1.0000000  1.0000000  1.0000000 -0.5773503
#> 96478   1.0000000  1.0000000  1.0000000  1.0000000 -0.5773503
#> 33835   1.0000000  1.0000000  1.0000000  1.0000000 -0.5773503
#> 51912   1.0000000  1.0000000  1.0000000  1.0000000 -0.5773503
#> 152477  1.0000000  1.0000000  1.0000000  1.0000000 -0.5773503
#> 33831   1.0000000  1.0000000  1.0000000  1.0000000 -0.5773503
#> 100279  1.0000000  1.0000000  1.0000000  1.0000000 -0.5773503
#> 53366  -0.5773503 -0.5773503 -0.5773503 -0.5773503  1.0000000

Значительно больше Пакет widyr предлагает простой способ:

library(widyr)
df %>%
  pairwise_cor(Article_Number, Document_Number, upper = FALSE)
#> # A tibble: 55 x 3
#>     item1  item2 correlation
#>     <int>  <int>       <dbl>
#>  1 115027 100288       1    
#>  2 115027  11754       0.577
#>  3 100288  11754       0.577
#>  4 115027  33908      -0.333
#>  5 100288  33908      -0.333
#>  6  11754  33908       0.577
#>  7 115027  96478      -0.333
#>  8 100288  96478      -0.333
#>  9  11754  96478       0.577
#> 10  33908  96478       1    
#> # … with 45 more rows

data

df <- structure(list(Document_Number = c(14198915L, 14198915L, 14198915L, 
14198917L, 14198917L, 14198917L, 14198917L, 14198917L, 14198917L, 
14198917L, 14198917L, 14198924L, 14200000L), Article_Number = c(115027L, 
100288L, 11754L, 33908L, 96478L, 33835L, 51912L, 152477L, 33831L, 
100279L, 11754L, 53366L, 53366L)), class = "data.frame", row.names = c(NA, 
-13L))
...