我想将数据帧转换为另一个数据帧。如果可能,在较少的命令中,使用dplyr
或tidyr
会很棒。
为了解析我使用library(rjson)
的坐标列表,这部分没问题,但是我无法进一步操作列表来获得我的结果。
如果您可以避免使用任何for
语句会很好,但只要解决问题,任何解决方案都是好的:)
输入:
df <- data.frame(code = c("12000", "89000"),
polygon = c("[[[11,12], [13,14], [15,16]], [[21, 22], [23,24], [25,26]]]",
"[[[81,82], [83,84], [85,86]]]"))
df
> df
code polygon
1 12000 [[[11,12], [13,14], [15,16]], [[21, 22], [23,24], [25,26]]]
2 89000 [[[81,82], [83,84], [85,86]]]
输入数据描述:
code
包含邮政编码polygon
包含一个或多个由其纬度 - 经度点对定义的多边形想要输出:
> wanted
a lon lat id
1 12000 11 12 1
2 12000 13 14 1
3 12000 15 16 1
4 12000 21 22 2
5 12000 23 24 2
6 12000 25 26 2
7 89000 81 82 1
8 89000 83 84 1
9 89000 85 86 1
我想使用ggplot绘制想要的data.frame。
答案 0 :(得分:6)
purrr
,dplyr
和jsonlite
解决方案:
df <- data.frame(code = c("12000", "89000"),
polygon = c("[[[11,12], [13,14], [15,16]], [[21, 22], [23,24], [25,26]]]",
"[[[81,82], [83,84], [85,86]]]"),
stringsAsFactors=FALSE)
library(purrr)
library(dplyr)
library(jsonlite)
make_coords <- function(x) {
fromJSON(x$polygon, simplifyMatrix=FALSE) %>%
map_df(~map_df(., ~setNames(as.data.frame(as.list(.)), c("lat", "lon"))), .id="id")
}
group_by(df, a=code) %>%
do(make_coords(.)) %>%
ungroup() %>%
select(a, lat, lon, id)
## # A tibble: 9 x 4
## a lat lon id
## <chr> <int> <int> <chr>
## 1 12000 11 12 1
## 2 12000 13 14 1
## 3 12000 15 16 1
## 4 12000 21 22 2
## 5 12000 23 24 2
## 6 12000 25 26 2
## 7 89000 81 82 1
## 8 89000 83 84 1
## 9 89000 85 86 1
这具有验证多边形数据的额外好处,因为您的示例ha [ds]无效JSON(我必须编辑初始示例中的最终]
)。
注意:
group_by
可以由dplyr::rowwise
或purrr::by_row
code
,将JSON转换为坐标列表,遍历该列表并从每个多边形中生成一个日期框,并为其指定位置ID。group_by
(将code
转变为a
),最里面的map_df
(lat
}&amp; lon
)以及最后由id
自动创建的map_df
。 rowwise
版本:
make_coords2 <- function(x) {
fromJSON(x$polygon, simplifyMatrix=FALSE) %>%
map_df(~map_df(., ~setNames(as.data.frame(as.list(.)), c("lat", "lon"))), .id="id") %>%
mutate(a=x$a)
}
select(df, a=code, polygon) %>%
rowwise() %>%
do(make_coords2(.)) %>%
ungroup() %>%
select(a, lat, lon, id)
by_row
版本:
make_coords3 <- function(x) {
fromJSON(x$polygon, simplifyMatrix=FALSE) %>%
map_df(~map_df(., ~setNames(as.data.frame(as.list(.)), c("lat", "lon"))), .id="id")
}
select(df, a=code, polygon) %>%
by_row(make_coords3, .collate="rows") %>%
select(a, lat, lon, id)
答案 1 :(得分:2)
这不是很好,但是对strsplit
,gsub
和unnest
的一些调用可以做很多事情:
]],
分割允许我们分隔多个多边形。id
row_number
轻松创建code
列
],
上分隔点对。[
和]
。,
分隔lon
和lat
。
df %>%
mutate(polygon = strsplit(polygon, ']],')) %>%
unnest() %>%
group_by(code) %>%
mutate(id = row_number(),
polygon = strsplit(polygon, '],')) %>%
unnest() %>%
mutate(polygon = gsub(']|\\[', '', polygon),
polygon = strsplit(polygon, ','),
lon = sapply(polygon, '[', 1),
lat = sapply(polygon, '[', 2)) %>%
select(-polygon)
Source: local data frame [9 x 4] Groups: code [2] code id lon lat <chr> <int> <chr> <chr> 1 12000 1 11 12 2 12000 1 13 14 3 12000 1 15 16 4 12000 2 21 22 5 12000 2 23 24 6 12000 2 25 26 7 89000 1 81 82 8 89000 1 83 84 9 89000 1 85 86
答案 2 :(得分:1)
我认为在df $ polygon [2]中有一个结束括号。如果删除它,您可以执行以下操作:
require(jsonlite)
require(reshape2)
parse_json <- function(polygon, code){
molten <- melt(fromJSON(polygon))
lat <- molten[which(molten$Var3==1), "value"]
lon <- molten[which(molten$Var3==2), "value"]
id <- molten[which(molten$Var3==1), "Var1"]
data.frame(code, lat, lon, id)
}
dat_raw <- mapply(parse_json, df$polygon, df$code, SIMPLIFY = FALSE, USE.NAMES = FALSE)
do.call(rbind, dat_raw)
这给了你:
code lat lon id
1 12000 11 12 1
2 12000 21 22 2
3 12000 13 14 1
4 12000 23 24 2
5 12000 15 16 1
6 12000 25 26 2
7 89000 81 82 1
8 89000 83 84 1
9 89000 85 86 1