Я пытаюсь воспроизвести меру «наибольшего сильно связанного компонента (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
Вам просто нужно количество узлов в наибольшем связном компоненте, разделенное на количество узлов во всем графе, поэтому length(V(largest_component(data, mode = "strong"))) / length(V(data))
даст вам LSCC, предполагая, что data
— это ваш объект igraph, представляющий сеть.
Итак, вы имеете в виду, что стоимость каждого банка должна составлять долю от общего числа банков, к которым можно получить доступ из этого узла?
Из статьи, которую вы цитируете, я могу понять vcount(largest_component(g, mode='strong')) / vcount(g)
. Однако мне кажется, что это не то, о чем вы пытаетесь попросить. Нам действительно нужно точное математическое определение того, чего вы хотите. До сих пор вы только сказали: «Он не дал нужных мне числовых значений, таких как степень, близость...»
Фрагмент данных, представленный в вопросе, содержит только исходящие соединения из одного банка, поэтому его недостаточно для демонстрации решения проблемы. Вот воспроизводимый пример игрушки, которого должно быть достаточно:
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 вместо этого). Прежде всего, приемлемо ли это? Если нет, то можно ли и как мне поместить оба направления в одну структуру данных? Или моя структура данных уже в порядке?
Кроме того, мне интересно, можно ли смешать код «самый большой_компонент» с вашим предложением (?). Вероятно, это будет способ определить так называемый самый большой компонент, такой как банк B.
@Eric, методология определяет направленные ребра, а это означает, что вам, вероятно, понадобятся и A ---> B, и B ---> A, иначе сделайте свой граф ненаправленным. В данном контексте под крупнейшим компонентом понимается связанная группа банков - мы не можем говорить о том, что банк Б является крупнейшим компонентом (он принадлежит к крупнейшему направленному компоненту). Логично, что самый большой компонент ваших данных с фактически ненаправленными краями будет содержать несколько банков, которые будут одинаково хорошо связаны между собой. Метод, который я показываю выше, позволяет найти банк с наибольшей связностью (банк B).
По какой-то причине я обнаружил, что все результаты всегда равны «1» во всех банках.
Проще говоря, когда доходность акций банка А приводит к увеличению доходности акций банка Б, я ставлю A --> B. Если доходность акций банка А увеличивается три раза за один квартал, я ставлю A --> B три раза подряд. Я никогда не ставил как A <--- B, вместо этого я всегда ставил это как B ---> A. Но, несмотря на эти четкие направляющие узлы, странно, что я всегда и во всех ситуациях всегда получаю 1 с.
@Эрик, это, по-видимому, потому, что вы можете связаться с любым банком из любого другого банка. Если все ваши потоки двунаправлены, то, вероятно, существуют цепочки связей, по которым вы можете следовать от любого банка к любому другому банку. Возможно, вам нужно только количество банков, с которыми каждый банк взаимодействует напрямую? Это очень легко посчитать. Если нет, то, возможно, подумайте, что именно вы ищете — кажется, вы изо всех сил пытаетесь точно определить, чего вы хотите.
На самом деле это первое. Если да, то что мне делать, если мои выходные данные продолжают получать их все время?
и если это снова масштабировать по количеству банков, я думаю, что это то, что мне нужно для измерения LSCC.
Когда я просто копирую и вставляю данные в свой лист Excel, подсчитываю, сколько раз каждый банк появляется в первом столбце i (поскольку я там, где он появляется все время), тогда я, кажется, получаю цифры по-разному для каждого банк. На самом деле столбец j, похоже, не поможет в этом процессе, поскольку мои данные показывают только «выход», а не «вход», потому что данные изначально помещаются только как i -> j. (как будто мне нужно показать j -> i, я просто снова возвращаю данные банка i в местоположение банка j).
@Эрик, так ты просто хочешь, чтобы количество банков, с которыми имеет дело каждый банк, было напрямую разделено на общее количество банков? Это правильно?
Я думаю, что в Python есть такой код для LSCC (или они могут называть его SCC), а в R, похоже, его нет. Не уверен, стоит ли на это тоже ссылаться.
Я имею в виду, что проблема вашего кода в отсутствии дубликатов. Я имел в виду, что мне могут понадобиться дубликаты, поскольку одни и те же причинно-следственные связи от одной и той же фирмы к другой той же фирме могут происходить несколько раз в одном и том же квартале.
Если вы не увидите полные данные, вы можете не понять, о чем я говорю. Несмотря на это, теперь я записал больше данных, показывающих, что из банка i поступает более одной фирмы. Но если вы знаете, как я могу предоставить остальные данные, пожалуйста, дайте мне знать.
@Эрик, проблема в том, что если все банки в вашем наборе данных подключаются ко всем другим банкам в вашем наборе данных, то LSCC равен 1. Это именно то, что говорят данные, и с этим ничего нельзя поделать.
Я думаю, вы неправильно понимаете. Когда банк i не подключается к банку j, я не включил его в набор данных. Но банк i может подключиться к банку j более одного раза в одном и том же квартале. Таким образом, необходимо различать, сколько раз банк i подключается к банку j в одном и том же квартале, а это может быть более одного раза.
@Эрик, но количество контактов каждый квартал не имеет абсолютно никакого отношения к LSCC, как это определено в документе. Вы совершенно правы в том, что я не понимаю, что вы пытаетесь вычислить; что бы это ни было, это не LSCC, и вы не сказали нам, что это такое. В любом случае ваш вопрос уже закрыт другими пользователями-экспертами, в том числе одним из авторов igraph, поскольку неясно, что вы пытаетесь вычислить. Вместо того, чтобы добавлять комментарии, задайте новый вопрос, в котором четко указано, что именно вы пытаетесь вычислить.
У меня уже есть другие сетевые меры. LSCC — это всего лишь дополнительный параметр, который я пытался вставить вместе с другими имеющимися у меня сетевыми мерами. Если LSCC не подходит в моем текущем контексте, возможно, я просто не включаю его. Например, если это банки только внутри одной страны, то, вероятно, расчет LSCC может быть бессмысленным, если они, по сути, должны быть все связаны, если принадлежат к крупнейшим долям рынка. Как вы думаете?
@Эрик, это мое предположение. Если все банки в вашей выборке могут и осуществляют транзакции друг с другом, то LSCC равен 1, и вы можете либо включить этот факт в свое описание, либо вообще исключить его, как само собой разумеющееся.
Спасибо, что поделились своими мыслями.
Используя данные из ответа Аллана Кэмерона, вот две функции, которые вычисляют 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()
, например.
Я имею в виду, что проблема вашего кода в отсутствии дубликатов. Я имел в виду, что мне могут понадобиться дубликаты, поскольку одни и те же причинно-следственные связи от одной и той же фирмы к другой той же фирме могут происходить несколько раз в одном и том же квартале.
Когда банк i не подключается к банку j, я не включил его в набор данных. Но банк i может подключиться к банку j более одного раза в одном и том же квартале. Таким образом, необходимо различать, сколько раз банк i подключается к банку j в одном и том же квартале, а это может быть более одного раза.
Код не создает график, я создал его с помощью
g<-graph_from_data_frame(data)
. Тогда я не понимаю проблему с самыми большими компонентами, граф связен, у него только один компонент,components(g)
. Что касается остальных мер, запуститеdegree(g)
и посмотрите этот пост RPubs.