整个 table 的转移概率

Transition probabilities for entire table

我有以下结构的 df:

sid step1 step2 step3 . . . . . step30

sid 是一个 id,步骤是通过一个网页的步骤,其中

  1. sids 最少两步
  2. sids最多三十步
  3. 没有重复的顺序页面(即页面刷新)
  4. 步骤都是字符串对象类型

我基本上想为每个唯一页面创建一个总转换概率——我得到一个 table/matrix,它对每个可能的页面都有一个转换概率。

我有大约 3k 个独立页面,所以我不知道这在计算上是否可行。

我也可以传递几页作为矩阵的参数,所以它不是 3000x3000 矩阵,可能是 1x3000 或 5x3000。事实上,我更愿意从这个开始并扩大规模直到它崩溃大声笑。

从概念开始

要构建转换矩阵,通常很容易先构建计数矩阵。然后可以划分计数以产生转移概率。

制作类似的东西:

            | to_site_A | to_site_B | ...
----------- +-----------+-----------+-----
from_site_A |
from_site_B |           counts
from_site_C |
...

第一次生产可能更简单:

from   | to     | count
-------+--------+-------
site_A | site_B |
site_A | site_C |
...

这是相同的信息,只是排列方式不同。

要做到这一点,如果您将当前数据重新排列成这样的结构,可能会更容易:

from   | to    
-------+-------
site_A | site_B
site_A | site_C
...

所以

  • 第 1 步:将数据放入转换的细长结构中
  • 第 2 步:计算所有成对转换
  • 第 3 步:将计数旋转或重新排列为方矩阵
第一步,将数据重新排列为细长

你可能想要这样的东西:

df_from_1_to_2 = df %>%
  select(from = step1, to = step2) %>%
  filter(!is.na(to))
df_from_2_to_3 = df %>%
  select(from = step2, to = step3) %>%
  filter(!is.na(to))
...
df_from_29_to_30 = df %>%
  select(from = step29, to = step30) %>%
  filter(!is.na(to))

long_list = rbind(df_from_1_to_2,
                  df_from_2_to_3,
                  ...
                  df_from_29_to_30)

不,这不是解决这个问题的最有效方法(通过代码或内存管理),但我们将专注于该方法。

第 2 步,计算所有成对转换

这很简单:

pairwise_count = long_list %>%
  group_by(from, to) %>%
  summarise(count = n())
第 3 步,将计数旋转或重新排列为方矩阵

此步骤只是更改数据的呈现方式,根据您的应用程序甚至可能不是必需的。

为了重新排列此类数据,我建议 pivot_wider 来自 tidyr 包:

count_matrix = pivot_wider(
  data = pairwise_count,
  names_from = to,
  names_prefix = "to",
  names_sep = "_",
  values_from = count,
)
编辑:获取概率而不是计数

有多个点可以从计数转换为概率,其中一个地方是在第 2 步:

pairwise_count = long_list %>%
  group_by(from, to) %>%
  summarise(count = n())

pairwise_prob = pairwise_count %>%
  group_by(from) %>%
  mutate(from_count = sum(count)) %>%
  mutate(prob = count / from_count) %>%
  select(from, to, prob)

然后您可以在第 3 步中使用 pairwise_prob 而不是 pairwise_count