การรวม Shapefile และ dataframe

Sep 17 2020

ฉันกำลังทำงานในRกับ dataframe ปกติ ( df) และ shapefile ( map2) CD116FPหุ้นคอลัมน์ทั่วไปเรียกว่า dfมี 103552 บรรทัดในขณะที่map2มี 444 ฉันกำลังโหลด shapefile ด้วยวิธีต่อไปนี้:

map2 <- read_sf ("D: /Data/tl_2019_us_cd116.shp")

สิ้นเป้าหมายของฉันคือการใช้ฟังก์ชั่นmapview()ในการดูแผนที่ที่รวมอยู่ในmap2กับ "ความรุนแรง" ที่อธิบายไว้ในคอลัมน์df np_scoresผมจึงไม่ต้องการให้ข้อสังเกตของที่ไม่ปรากฏในdfmap2

นี่คือความคิดและความล้มเหลวของฉัน:

  1. หากวัตถุทั้งสองนี้เป็นดาต้าเฟรมปกติตัวเลือกที่สมเหตุสมผลจะถูกใช้merge()เพื่อรวมวัตถุทั้งสองอย่างไรก็ตามหากคุณใช้ฟังก์ชันนั้นในกรณีนี้วัตถุที่ได้รับจะสูญเสียคุณสมบัติเชิงพื้นที่และmapviewไม่รู้ว่าจะอ่านอย่างไร

  2. อีกวิธีหนึ่งที่ฉันใช้คือลองใช้โค้ดบรรทัดนี้:

map2m <-data.frame (map2, df [match (map2$CD116FP, df$CD116FP),])

แต่ผลลัพธ์มีขนาดที่ใหญ่เกินไป (ใหญ่กว่า 444 บรรทัด) และmapviewเกิดปัญหาเมื่อพยายามที่จะพล็อตแผนที่ที่ต้องการ

  1. ในที่สุดฉันก็ใช้กำลังดุร้ายเต็มรูปแบบและเพิ่งสร้างลูปเพื่อเพิ่มคอลัมน์npไปที่map2:
map2$np=10 for (i in c(1:nrow(map2))) { for (j in c(1:nrow(df))) { if (identical(map2$CD116FP[i],df$CD116FP[j])) {map2$np[i]=df$np_score[j]} else {map2$np[i]=0}  
}
}  

อย่างไรก็ตามวิธีนี้ใช้เวลามากเกินไปเนื่องจากขนาดของดาต้าเฟรมของฉัน

คุณมีข้อเสนอแนะใด?

คำตอบ

3 AllanCameron Sep 19 2020 at 22:24

ฉันงงกับโครงสร้างข้อมูลของคุณเล็กน้อย ของคุณdfมีมากกว่า 100,000 แถวดังนั้นฉันคาดเดาว่าเหตุการณ์เดียวกันCD116FPนี้จะเกิดขึ้นหลายครั้งdfและnpscoreน่าจะแตกต่างกันไปตามอินสแตนซ์เหล่านี้ หากคุณต้องการรวมสิ่งเหล่านี้เข้ากับmap2คุณจะต้องรวมเข้าด้วยกันก่อน

ลองสร้างการตั้งค่าที่คล้ายกันใหม่:

library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1

map2 <- read_sf("C:/users/administrator/documents/shape/tl_2019_us_cd116.shp")

set.seed(69)

df <- data.frame(CD116FP = sprintf("%02d", sample(0:99, 103552, TRUE)),
                 npscores = runif(103552))

head(df)
#>   CD116FP  npscores
#> 1      95 0.6927742
#> 2      80 0.8543845
#> 3      90 0.5220353
#> 4      01 0.1449647
#> 5      76 0.9876543
#> 6      38 0.5629950

ฉันได้ทำให้dfมีจำนวนแถวเดียวกันกับที่ข้อมูลของคุณต้องแสดงโซลูชันนี้จะปรับขนาดตามปัญหาของคุณ

มารวมnpscoresกับdplyr:

library(dplyr)
df_sum <- df %>% 
  filter(CD116FP %in% map2$CD116FP) %>% group_by(CD116FP) %>% summarise(npscores = mean(npscores)) map2$npscores <- df_sum$npscores[match(map2$CD116FP, df_sum$CD116FP)]

ตอนนี้map2มีการรวมที่npscoresเราสามารถพล็อต - ตัวอย่างเช่นใน ggplot:

library(ggplot2)

ggplot(map2) + 
  geom_sf(aes(fill = npscores)) +
  coord_sf(xlim = c(-180, -60),
            ylim = c(15, 70)) +
  scale_fill_gradient(low = "red", high = "gold")

หรือใน mapview:

library(mapview)
mapView(map2, zcol = "npscores")

สร้างเมื่อ 2020-09-19 โดยแพ็คเกจ reprex (v0.3.0)

Alexa Sep 25 2020 at 17:24

ฉันมีโชคบางอย่างที่ใช้แบบเก่าmergeจากแพ็คเกจพื้นฐาน นี่คือข้อความที่ตัดตอนมาจากงานของฉันเองสิ่งนี้ควรมีค่าสำหรับคุณ :-)

my_data <- read_excel("TraderDataRaw.xlsx", 
      sheet = "fsa", 
      col_types= c("text","text","text","logical","numeric","numeric")) %>% 
      mutate(resp_rate=mailed/responses)

my_map <- st_read("lfsa000b16a_e.shp", stringsAsFactors = FALSE) 

my_merged_data <- merge(my_map, my_data, 
      by.x=c("CFSAUID","PRUID","PRNAME"), 
      by.y=c("CFSAUID","PRUID","PRNAME"))