0

这是一个新手 R 问题。我开始探索将 R 用于网站分析。我有一组页面视图事件,它们具有公共属性以及依赖于页面的任意属性集。例如,所有事件都有一个userId, createdAt, and pageId,但"signup"页面可能有一个特殊属性origin,其值可以是"adwords"or"organic"等​​。

在 JSON 中,数据可能如下所示:

[
   {
      "userId":null,
      "pageId":"home",
      "sessionId":"abcd",
      "createdAt":1381013741,
      "parameters":{},
   },
   {
      "userId":123,
      "pageId":"signup",
      "sessionId":"abcd",
      "createdAt":1381013787,
      "parameters":{
         "origin":"adwords",
         "campaignId":4
      }
   }
]

我一直在努力在 R 数据结构中有效地表示这些数据。特别是我需要能够根据任意键/值对的条件对事件列表进行子集化,例如,选择所有事件,其pageId=="signup"origin=="adwords".

用于任意参数的键有足够的多样性,因此为每个可能的键创建稀疏填充的列似乎是不合理的。

我目前正在做的是将数据预处理成两个 CSV 文件,core_properties.csv并且parameters.csv格式为:

# core_properties.csv (one record per pageview)
userId,pageId,sessionId,createdAt
,home,abcd
123,signup,abcd,1381013741
...

# parameters.csv (one record per k/v pair)
row,key,value   # <- "row" here denotes the record index in core_properties.csv
1,origin,adwords
1,campaignId,4
...

然后我将read.table每个文件放入一个数据框中,我现在尝试将 k/v 对存储在核心事件数据框的单元格内的列表(名称=键)。这是很多尴尬的试验和错误,到目前为止我发现的最佳方法如下:

events <- read.csv('core_properties.csv', header=TRUE)
parameters <- read.csv('parameters.csv',
   header=TRUE,colClasses=c("character","character","character"))
paramLists <- sapply(1:nrow(events), function(x) { list() })
apply(parameters,1,function(x) {
   paramLists [[ as.numeric(x[["row"]]) ]][[ x[["key"]] ]] <<- x[["value"]] })
events$parameters <- paramLists 

我现在可以通过以下语法访问第一个事件的 origin 属性:events[1,][["parameters"]][[1]][["origin"]]- 请注意,由于某种原因,它需要一个额外的[[1]]下标。数据框似乎不喜欢将列表作为单元格的单独值:

> events[1,][["parameters"]] <- list()
Error in `[[<-.data.frame`(`*tmp*`, "parameters", value = list()) : 
   replacement has 0 rows, data has 1

是否有处理此类数据的最佳实践?我没有发现它在手册和教程中讨论过。

谢谢!

4

1 回答 1

0

您可以在 R 中使用嵌套列表来很好地映射到 JSON。我已经展示了一个简单的示例,您可以根据参数来源进行过滤。

dat <- list(
  list(userId = NULL, pageId = "home", createdAt = 1381013741, parameters = list()),
  list(userId = NULL, pageId = "new", createdAt = 1381013741, parameters = list(origin = 'adwords', campaignId = 4))
)

Filter(function(l){length(l) > 0 && l$parameters$origin == 'adwords'}, dat)
于 2013-10-06T12:57:11.623 回答