2

我有一个形式的 R 数据框:

Country Region  Year    V1  V2
AAAA    XXXX    2001    12  13
BBBB    YYYY    2001    14  15
AAAA    XXXX    2002    36  56
AAAA    XXXX    1999    45  67

并希望生成一个等效于以下形式的 JSON:

[
  {"Country": "AAAA",
   "Region":"XXXX",
    "V1": [ [1999,45], [2001,12] , [2002,36] ],
    "V2":[ [1999,67], [2001,13] , [2002,56] ]
  },
  {"Country": "BBBB",
   "Region":"YYYY",
   "V1":[ [2001,14] ],
   "V2":[ [2001,15] ]
  }
]

我想象这需要:

  1. 按国家和地区分组
  2. 在组内按年份排序
  3. 对于 V1、V2 中剩余的每一列 Vx(可以有任意名称的任意数量的列),生成一个包含列表元素 [Year, Vx] 的列表,用于有序年份

但我正在努力寻找一种方法来做到这一点?

4

2 回答 2

3

这是另一种方法。

dat <- read.table(textConnection("Country Region  Year    V1  V2
AAAA    XXXX    2001    12  13
BBBB    YYYY    2001    14  15
AAAA    XXXX    2002    36  56
AAAA    XXXX    1999    45  67"), header = TRUE)

我们添加了两个帮助函数来一起压缩向量,以及一个自定义排序函数,它按给定位置的元素对列表进行排序。

#' Pluck element
pluck_ = function (element){
  function(x) x[[element]]
}

#' Zip two vectors
zip_ <- function(..., names = F){
  x = list(...)
  y = lapply(seq_along(x[[1]]), function(i) lapply(x, pluck_(i)))
  if (names) names(y) = seq_along(y)
  return(y)
}

#' Sort a vector based on elements at a given position
sort_ <- function(v, i = 1){
  v[sort(sapply(v, '[[', i), index.return = T)$ix]
}

是时候把东西放在一起并使用split-apply-combine魔法来获得你想要的输出了。

library(plyr)
dat2 <- dlply(dat, .(Country, Region), function(d){
  list(
    Country = d$Country[1],
    Region = d$Region[1],
    V1 = sort_(zip_(d$Year, d$V1)),
    V2 = sort_(zip_(d$Year, d$V2))
  )
})
cat(rjson::toJSON(setNames(dat2, NULL)))

这给了你输出

[
  {"Country":"AAAA",
   "Region":"XXXX",
   "V1":[[1999,45],[2001,12],[2002,36]],
   "V2":[[1999,67],[2001,13],[2002,56]]
  },
  {"Country":"BBBB",
   "Region":"YYYY",
   "V1":[[2001,14]],
   "V2":[[2001,15]]
  }
]
于 2013-11-01T14:53:40.850 回答
0

这是一种杂乱无章的功能(您可以轻松地添加按 V1 和 V2 数组的年份排序):

dat <- read.table(textConnection(
'Country Region  Year    V1  V2
AAAA    XXXX    2001    12  13
BBBB    YYYY    2001    14  15
AAAA    XXXX    2002    36  56
AAAA    XXXX    1999    45  67'
), header=TRUE, stringsAsFactors=FALSE)

library(plyr); library(RJSONIO)
myfunc <- function(nn)
{
  tt <- split(nn, nn$Country)
  bar <- function(w){
    foo <- function(x, y, z) paste(x[y], x[z], sep=",")
    V1 <- as.character(apply(w, 1, foo, y="Year", z="V1"))
    V2 <- as.character(apply(w, 1, foo, y="Year", z="V2"))
    datlist <- list(Country = unique(w$Country), 
                    Region = unique(w$Region), 
                    V1 = V1, V2=V2)
  }
  datlist <- lapply(tt, bar)
  names(datlist) <- NULL
  RJSONIO::toJSON(datlist)
}

cat(myfunc(dat))

[
 {
   "Country": "AAAA",
   "Region": "XXXX",
   "V1": [ "2001,12", "2002,36", "1999,45" ],
   "V2": [ "2001,13", "2002,56", "1999,67" ] 
 },
 {
   "Country": "BBBB",
   "Region": "YYYY",
   "V1": "2001,14",
   "V2": "2001,15" 
  } 
]
于 2013-11-01T14:34:06.820 回答