从R中的分组数据帧重塑JSON输出

时间:2013-11-01 12:46:38

标签: r

我有一个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 个答案:

答案 0 :(得分: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]]
  }
]

答案 1 :(得分: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" 
  } 
]