Эквивалент меры «самый большой сильно связный компонент (LSCC)» в igraph?

Я пытаюсь воспроизвести меру «наибольшего сильно связанного компонента (LSCC)», которая, похоже, отсутствует в кодах пакета общего сетевого анализа R 'igraph'. Лучшее, что я смог найти, это команда «largest_comComponent» из пакета «igraph», но она дает мне только список названий банков без нужных мне номеров. Так что я предполагаю, что это всего лишь сортировка названий фирм вместо того, чтобы давать мне нужные мне значения, как это делает красный квадрат (ниже) на снимке статьи.

Как я могу воспроизвести значения сетевого анализа LSCC с помощью программы R?

Я пытался использовать коды R, как в по этой ссылке

Однако он не дал нужных мне числовых значений, таких как степень, близость, центральность и т. д. типов числовых значений сети.

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

> library(igraph)
> largest_component(data,mode = "strong")
IGRAPH cd5f7d1 DN-- 94 988 -- 
+ attr: name (v/c)
+ edges from cd5f7d1 (vertex names):
 [1] ABCB US Equity->COLB US Equity ABCB US Equity->FULT US Equity ABCB US Equity->GABC US Equity ABCB US Equity->INDB US Equity
 [5] ABCB US Equity->BOH US Equity  ABCB US Equity->HOPE US Equity ABCB US Equity->NTRS US Equity ABCB US Equity->ONB US Equity 
 [9] ABCB US Equity->PB US Equity   ABCB US Equity->RNST US Equity ABCB US Equity->STBA US Equity ABCB US Equity->SASR US Equity
[13] ABCB US Equity->SBCF US Equity ABCB US Equity->SBSI US Equity ABCB US Equity->TRMK US Equity ABCB US Equity->UBSI US Equity
[17] ABCB US Equity->WFC US Equity  ABCB US Equity->SRCE US Equity ABCB US Equity->FFBC US Equity ABCB US Equity->PFBC US Equity
[21] ABCB US Equity->CADE US Equity C US Equity   ->CFR US Equity  C US Equity   ->EEFT US Equity C US Equity   ->NBTB US Equity
[25] C US Equity   ->OCFC US Equity C US Equity   ->PNFP US Equity C US Equity   ->PB US Equity   C US Equity   ->STBA US Equity
[29] C US Equity   ->SASR US Equity C US Equity   ->SBSI US Equity C US Equity   ->WABC US Equity C US Equity   ->BANR US Equity
+ ... omitted several edges
> components(gD_12_2022,mode = "strong")

И фрагмент моих данных выглядит следующим образом:

 Date        i               j
09/2005 ABCB US Equity  CHCO US Equity
09/2005 ABCB US Equity  CHCO US Equity
09/2005 ABCB US Equity  CHCO US Equity
09/2005 ABCB US Equity  COLB US Equity
09/2005 ABCB US Equity  COLB US Equity
09/2005 ABCB US Equity  COLB US Equity
09/2005 ABCB US Equity  FITB US Equity
09/2005 ABCB US Equity  FNB US Equity
09/2005 ABCB US Equity  HBAN US Equity
09/2005 ABCB US Equity  HBAN US Equity
09/2005 ABCB US Equity  BOH US Equity
09/2005 ABCB US Equity  BOH US Equity
09/2005 ABCB US Equity  BOH US Equity
09/2005 ABCB US Equity  MTB US Equity
09/2005 ABCB US Equity  PNFP US Equity
09/2005 ABCB US Equity  SYBT US Equity
09/2005 ABCB US Equity  SYBT US Equity
09/2005 ABCB US Equity  SYBT US Equity
09/2005 ABCB US Equity  SIVBQ US Equity
09/2005 ABCB US Equity  SIVBQ US Equity
09/2005 ABCB US Equity  SIVBQ US Equity
09/2005 ABCB US Equity  TRMK US Equity
09/2005 ABCB US Equity  WFC US Equity
09/2005 ABCB US Equity  ZION US Equity
09/2005 ABCB US Equity  ZION US Equity
09/2005 ABCB US Equity  ZION US Equity
09/2005 ABCB US Equity  BRKL US Equity
09/2005 ABCB US Equity  BRKL US Equity
09/2005 ABCB US Equity  BRKL US Equity
09/2005 ABCB US Equity  CFFN US Equity

Что касается других сетевых показателей, таких как степень, центральность и т. д., как я уже упоминал, у меня нет проблем с их созданием, поскольку они работают, как показано ниже (показан фрагмент моих результатов). Только LSCC я не нашел подходящего кода для запуска или выполнения из R:

Firms           Date    Degree       Closeness  Betweenness Clustering  Eigenvector
ABCB.US.Equity  09_2005 0.494623656 0.540697674 0.00484853  0.391304348 0.128802216
CHCO.US.Equity  09_2005 0.784946237 0.540697674 0.009498633 0.386809269 0.496275598
COLB.US.Equity  09_2005 0.612903226 0.550295858 0.007786027 0.386243386 0.265205502
FITB.US.Equity  09_2005 0.838709677 0.611842105 0.015768372 0.374307863 0.257392456
FNB.US.Equity   09_2005 0.494623656 0.436619718 0.002341893 0.383333333 0.47983247
HBAN.US.Equity  09_2005 0.64516129  0.510989011 0.008919628 0.342245989 0.507258004
BOH.US.Equity   09_2005 0.462365591 0.502702703 0.003176559 0.418300654 0.230633224
MTB.US.Equity   09_2005 0.731182796 0.513812155 0.011603933 0.346031746 0.560058904
PNFP.US.Equity  09_2005 0.731182796 0.502702703 0.006913042 0.406722689 0.668115579
SYBT.US.Equity  09_2005 1.494623656 0.611842105 0.041680331 0.352685051 0.70931023

Код не создает график, я создал его с помощью g<-graph_from_data_frame(data). Тогда я не понимаю проблему с самыми большими компонентами, граф связен, у него только один компонент, components(g). Что касается остальных мер, запустите degree(g) и посмотрите этот пост RPubs.

Rui Barradas 24.08.2024 20:48

Вам просто нужно количество узлов в наибольшем связном компоненте, разделенное на количество узлов во всем графе, поэтому length(V(largest_component(data, mode = "strong"))) / length(V(data)) даст вам LSCC, предполагая, что data — это ваш объект igraph, представляющий сеть.

Allan Cameron 25.08.2024 01:06

Итак, вы имеете в виду, что стоимость каждого банка должна составлять долю от общего числа банков, к которым можно получить доступ из этого узла?

Allan Cameron 25.08.2024 12:04

Из статьи, которую вы цитируете, я могу понять vcount(largest_component(g, mode='strong')) / vcount(g). Однако мне кажется, что это не то, о чем вы пытаетесь попросить. Нам действительно нужно точное математическое определение того, чего вы хотите. До сих пор вы только сказали: «Он не дал нужных мне числовых значений, таких как степень, близость...»

Szabolcs 26.08.2024 10:50
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
4
123
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Фрагмент данных, представленный в вопросе, содержит только исходящие соединения из одного банка, поэтому его недостаточно для демонстрации решения проблемы. Вот воспроизводимый пример игрушки, которого должно быть достаточно:

library(igraph)

set.seed(1)

d <- replicate(2, sample(paste("Bank", LETTERS[1:10]), 10, TRUE)) |>
  as.data.frame()

d <- unique(d[d[[1]] != d[[2]], ])
data <- graph_from_data_frame(d)

plot(data)

Судя по моему прочтению вашего методологического документа, LSCC — это доля других банков в наборе данных, к которой можно получить доступ из каждого банка, следуя только исходящим краям. Мы можем найти это igraph с помощью функции subcomponent. Например, чтобы найти все банки, до которых можно добраться из банка B, мы можем сделать:

subcomponent(data, V(data)["Bank B"], "out")
#> + 5/9 vertices, named, from 4b4f304:
#> [1] Bank B Bank G Bank E Bank I Bank F

Вы можете подтвердить, что банки G, E, I и F доступны из банка B в приведенном выше примере.

Мы заинтересованы в получении доли всех банков, которых может достичь банк B (исключая самого себя). Это будет просто количество узлов в подкомпоненте (минус банк B), деленное на общее количество банков (минус банк B). Другими словами:

(length(subcomponent(data, V(data)["Bank B"], "out")) - 1) / (length(V(data)) - 1)
#> [1] 0.5

Это число означает, что из банка B можно связаться с половиной других банков.

Чтобы получить результаты для всех банков, мы можем использовать lapply:

result <- lapply(V(data), function(v) {
   (length(subcomponent(data, v, "out")) - 1) / (length(V(data)) - 1)
  })

result
#> $`Bank I`
#> [1] 0.125
#> 
#> $`Bank D`
#> [1] 0.125
#> 
#> $`Bank G`
#> [1] 0.375
#> 
#> $`Bank A`
#> [1] 0.375
#> 
#> $`Bank B`
#> [1] 0.5
#> 
#> $`Bank C`
#> [1] 0.25
#> 
#> $`Bank E`
#> [1] 0.125
#> 
#> $`Bank J`
#> [1] 0
#> 
#> $`Bank F`
#> [1] 0

И если вы хотите это в фрейме данных, вы можете сделать:

result |>
  as.data.frame(check.names = FALSE) |>
  t() |>
  as.data.frame() |>
  tibble::rownames_to_column() |>
  setNames(c('Bank', "LSCC")) |>
  dplyr::arrange(Bank)
#>     Bank  LSCC
#> 1 Bank A 0.375
#> 2 Bank B 0.500
#> 3 Bank C 0.250
#> 4 Bank D 0.125
#> 5 Bank E 0.125
#> 6 Bank F 0.000
#> 7 Bank G 0.375
#> 8 Bank I 0.125
#> 9 Bank J 0.000

Спасибо. На самом деле, я расположил данные банка так, чтобы они передавались из банка i в банк j в одном направлении только для целей упорядочения данных. Если бы я хотел показать, что банк j также влияет на банк i, то я переключаю их позицию и снова помещаю в соответствии с банком i в позицию банка j. (например, если A --> B и A <--- B, я записываю как A ---> B и B ---> A вместо этого). Прежде всего, приемлемо ли это? Если нет, то можно ли и как мне поместить оба направления в одну структуру данных? Или моя структура данных уже в порядке?

Eric 25.08.2024 14:22

Кроме того, мне интересно, можно ли смешать код «самый большой_компонент» с вашим предложением (?). Вероятно, это будет способ определить так называемый самый большой компонент, такой как банк B.

Eric 25.08.2024 14:30

@Eric, методология определяет направленные ребра, а это означает, что вам, вероятно, понадобятся и A ---> B, и B ---> A, иначе сделайте свой граф ненаправленным. В данном контексте под крупнейшим компонентом понимается связанная группа банков - мы не можем говорить о том, что банк Б является крупнейшим компонентом (он принадлежит к крупнейшему направленному компоненту). Логично, что самый большой компонент ваших данных с фактически ненаправленными краями будет содержать несколько банков, которые будут одинаково хорошо связаны между собой. Метод, который я показываю выше, позволяет найти банк с наибольшей связностью (банк B).

Allan Cameron 25.08.2024 14:42

По какой-то причине я обнаружил, что все результаты всегда равны «1» во всех банках.

Eric 25.08.2024 15:08

Проще говоря, когда доходность акций банка А приводит к увеличению доходности акций банка Б, я ставлю A --> B. Если доходность акций банка А увеличивается три раза за один квартал, я ставлю A --> B три раза подряд. Я никогда не ставил как A <--- B, вместо этого я всегда ставил это как B ---> A. Но, несмотря на эти четкие направляющие узлы, странно, что я всегда и во всех ситуациях всегда получаю 1 с.

Eric 25.08.2024 15:13

@Эрик, это, по-видимому, потому, что вы можете связаться с любым банком из любого другого банка. Если все ваши потоки двунаправлены, то, вероятно, существуют цепочки связей, по которым вы можете следовать от любого банка к любому другому банку. Возможно, вам нужно только количество банков, с которыми каждый банк взаимодействует напрямую? Это очень легко посчитать. Если нет, то, возможно, подумайте, что именно вы ищете — кажется, вы изо всех сил пытаетесь точно определить, чего вы хотите.

Allan Cameron 25.08.2024 15:18

На самом деле это первое. Если да, то что мне делать, если мои выходные данные продолжают получать их все время?

Eric 25.08.2024 15:20

и если это снова масштабировать по количеству банков, я думаю, что это то, что мне нужно для измерения LSCC.

Eric 25.08.2024 15:24

Когда я просто копирую и вставляю данные в свой лист Excel, подсчитываю, сколько раз каждый банк появляется в первом столбце i (поскольку я там, где он появляется все время), тогда я, кажется, получаю цифры по-разному для каждого банк. На самом деле столбец j, похоже, не поможет в этом процессе, поскольку мои данные показывают только «выход», а не «вход», потому что данные изначально помещаются только как i -> j. (как будто мне нужно показать j -> i, я просто снова возвращаю данные банка i в местоположение банка j).

Eric 25.08.2024 15:30

@Эрик, так ты просто хочешь, чтобы количество банков, с которыми имеет дело каждый банк, было напрямую разделено на общее количество банков? Это правильно?

Allan Cameron 25.08.2024 15:31

Я думаю, что в Python есть такой код для LSCC (или они могут называть его SCC), а в R, похоже, его нет. Не уверен, стоит ли на это тоже ссылаться.

Eric 25.08.2024 15:42

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

Eric 26.08.2024 01:19

Если вы не увидите полные данные, вы можете не понять, о чем я говорю. Несмотря на это, теперь я записал больше данных, показывающих, что из банка i поступает более одной фирмы. Но если вы знаете, как я могу предоставить остальные данные, пожалуйста, дайте мне знать.

Eric 26.08.2024 11:33

@Эрик, проблема в том, что если все банки в вашем наборе данных подключаются ко всем другим банкам в вашем наборе данных, то LSCC равен 1. Это именно то, что говорят данные, и с этим ничего нельзя поделать.

Allan Cameron 26.08.2024 13:09

Я думаю, вы неправильно понимаете. Когда банк i не подключается к банку j, я не включил его в набор данных. Но банк i может подключиться к банку j более одного раза в одном и том же квартале. Таким образом, необходимо различать, сколько раз банк i подключается к банку j в одном и том же квартале, а это может быть более одного раза.

Eric 26.08.2024 14:13

@Эрик, но количество контактов каждый квартал не имеет абсолютно никакого отношения к LSCC, как это определено в документе. Вы совершенно правы в том, что я не понимаю, что вы пытаетесь вычислить; что бы это ни было, это не LSCC, и вы не сказали нам, что это такое. В любом случае ваш вопрос уже закрыт другими пользователями-экспертами, в том числе одним из авторов igraph, поскольку неясно, что вы пытаетесь вычислить. Вместо того, чтобы добавлять комментарии, задайте новый вопрос, в котором четко указано, что именно вы пытаетесь вычислить.

Allan Cameron 26.08.2024 14:26

У меня уже есть другие сетевые меры. LSCC — это всего лишь дополнительный параметр, который я пытался вставить вместе с другими имеющимися у меня сетевыми мерами. Если LSCC не подходит в моем текущем контексте, возможно, я просто не включаю его. Например, если это банки только внутри одной страны, то, вероятно, расчет LSCC может быть бессмысленным, если они, по сути, должны быть все связаны, если принадлежат к крупнейшим долям рынка. Как вы думаете?

Eric 26.08.2024 14:29

@Эрик, это мое предположение. Если все банки в вашей выборке могут и осуществляют транзакции друг с другом, то LSCC равен 1, и вы можете либо включить этот факт в свое описание, либо вообще исключить его, как само собой разумеющееся.

Allan Cameron 26.08.2024 15:09

Спасибо, что поделились своими мыслями.

Eric 26.08.2024 15:24

Используя данные из ответа Аллана Кэмерона, вот две функции, которые вычисляют LSCC.

library(igraph)

LSCC1 <- function(x) {
  d <- distances(x, mode = "out")
  rowSums(d > 0L & is.finite(d))/(length(V(x)) - 1L)
}

LSCC2 <- function(x) {
  paths <- lapply(V(x), \(v) all_shortest_paths(x, from = v, mode = "out"))
  sapply(paths, \(p) {
    sum(p[["nrgeo"]] > 0) - 1L
  })/(length(V(x)) - 1L)
}

LSCC1(data)
#> Bank I Bank D Bank G Bank A Bank B Bank C Bank E Bank J Bank F 
#>  0.125  0.125  0.375  0.375  0.500  0.250  0.125  0.000  0.000
LSCC2(data)
#> Bank I Bank D Bank G Bank A Bank B Bank C Bank E Bank J Bank F 
#>  0.125  0.125  0.375  0.375  0.500  0.250  0.125  0.000  0.000

Created on 2024-08-25 with reprex v2.1.0


Примечание

Чтобы вывести data.frame, передайте as.data.frame и исправьте имена столбцов. В выводе ниже имена строк являются именами вершин.

LSCC1(data) |> as.data.frame()
#>        LSCC1(data)
#> Bank I       0.125
#> Bank D       0.125
#> Bank G       0.375
#> Bank A       0.375
#> Bank B       0.500
#> Bank C       0.250
#> Bank E       0.125
#> Bank J       0.000
#> Bank F       0.000

Created on 2024-08-25 with reprex v2.1.0

У @Eric igraph есть функция упростить, которая возвращает график без дубликатов. Его выходные данные всегда представляют собой график, даже если входные данные представляют собой мультиграф. data |> simplify() |> LSCC1(), например.

Rui Barradas 25.08.2024 22:58

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

Eric 26.08.2024 01:16

Когда банк i не подключается к банку j, я не включил его в набор данных. Но банк i может подключиться к банку j более одного раза в одном и том же квартале. Таким образом, необходимо различать, сколько раз банк i подключается к банку j в одном и том же квартале, а это может быть более одного раза.

Eric 26.08.2024 14:23

Другие вопросы по теме