ฉันจะทำการวิเคราะห์ส่วนประกอบหลักทางภูมิศาสตร์ด้วยการใช้ ArcGIS, Python และ SPSS / R ได้อย่างไร


32

ฉันอยู่หลังคำอธิบาย / ระเบียบวิธีสำหรับการดำเนินการวิเคราะห์องค์ประกอบหลักทางภูมิศาสตร์ถ่วงน้ำหนัก(GWPCA) ฉันมีความสุขที่ใช้ Python สำหรับส่วนใดส่วนหนึ่งของนี้และฉันคิดว่า SPSS หรือ R ถูกใช้เพื่อเรียกใช้ PCA กับตัวแปรถ่วงน้ำหนักทางภูมิศาสตร์

ชุดข้อมูลของฉันประกอบด้วยตัวแปรอิสระ 30 ตัวที่วัดได้ทั่วระบบสำรวจสำมะโนประชากร ~ 550 (เรขาคณิตเวกเตอร์)

ฉันรู้ว่านี่เป็นคำถามที่โหลด แต่เมื่อฉันค้นหาและค้นหาดูเหมือนว่าจะไม่มีทางออกใด ๆ สิ่งที่ฉันเจอคือสมการทางคณิตศาสตร์ที่อธิบายองค์ประกอบพื้นฐานของ GWPCA (และ GWR) สิ่งที่ฉันเป็นหลังจากนั้นถูกนำไปใช้มากขึ้นในแง่ที่ว่าฉันกำลังมองหาสิ่งที่ขั้นตอนสำคัญที่ฉันต้องประสบความสำเร็จในการรับจากข้อมูลดิบกับผลลัพธ์ GWPCA


ฉันต้องการขยายในส่วนแรกของการแก้ไขนี้เนื่องจากความคิดเห็นที่ได้รับด้านล่าง

เพื่อที่อยู่พอล ...

ฉันอ้างอิงความสนใจของฉันใน GWPCA จากเอกสารต่อไปนี้:

Lloyd, CD, (2010) การวิเคราะห์ลักษณะประชากรโดยใช้การวิเคราะห์องค์ประกอบหลักทางภูมิศาสตร์: กรณีศึกษาไอร์แลนด์เหนือในปี 2544 คอมพิวเตอร์สิ่งแวดล้อมและระบบเมือง 34 (5), หน้า 339-399

สำหรับผู้ที่ไม่สามารถเข้าถึงวรรณกรรมฉันได้แนบภาพหน้าจอของส่วนเฉพาะที่อธิบายคณิตศาสตร์ด้านล่าง:

บทความ

และเพื่อที่อยู่ whuber ...

โดยไม่ต้องลงรายละเอียด (การรักษาความลับ) เรากำลังพยายามลดตัวแปร 30 ตัวซึ่งเราเชื่อว่าเป็นตัวชี้วัดที่ดีมาก (แม้ว่าจะอยู่ในระดับโลก) ไปยังชุดส่วนประกอบที่มีค่า eigen มากกว่า 1 โดยการคำนวณส่วนประกอบน้ำหนักทางภูมิศาสตร์ เพื่อทำความเข้าใจกับความแปรปรวนในท้องถิ่นที่อธิบายโดยส่วนประกอบเหล่านี้

ฉันคิดว่าเป้าหมายหลักของเราคือการพิสูจน์แนวคิดของ GWPCA นั่นคือแสดงลักษณะที่ชัดเจนเชิงพื้นที่ของข้อมูลของเราและเราไม่สามารถพิจารณาตัวแปรอิสระทั้งหมดเพื่ออธิบายในระดับโลก แต่ระดับท้องถิ่น (ละแวกใกล้เคียง) ที่แต่ละองค์ประกอบจะระบุจะช่วยเราในการทำความเข้าใจกับธรรมชาติของข้อมูลของเราในหลายมิติ

เราหวังว่าจะทำแผนที่ร้อยละของความแปรปรวนที่คิดเป็นสัดส่วนโดยแต่ละองค์ประกอบ (แยกต่างหาก) เพื่อทำความเข้าใจขอบเขตของพื้นที่ใกล้เคียงที่อธิบายโดยส่วนประกอบที่เป็นปัญหา บางทีตัวอย่างการทำแผนที่อื่น ๆ แต่ไม่มีใครนึกถึงในขณะนี้

นอกจากนี้:

คณิตศาสตร์ที่อยู่เบื้องหลัง GWPCA นั้นเกินกว่าสิ่งที่ฉันเข้าใจเนื่องจากภูมิหลังของฉันในการวิเคราะห์ทางภูมิศาสตร์และสถิติทางสังคม แอปพลิเคชันของคณิตศาสตร์เป็นสิ่งสำคัญที่สุดนั่นคือฉันจะเชื่อมต่อกับตัวแปร / สูตรเหล่านี้อย่างไร


1
ฉันไม่รู้วิธีแก้ปัญหากล่องใน R แต่ก็ไม่ควรยากเกินไป กรุณาโพสต์คณิตศาสตร์ที่เกี่ยวข้องหากคุณต้องการความคิดเห็นมากกว่า: "R อาจทำสิ่งนี้ได้"
Paul Hiemstra

2
คุณกำลังมองหาผลลัพธ์ประเภทใด ค่าลักษณะเฉพาะที่ใหญ่ที่สุด จำนวนองค์ประกอบหลักโดยประมาณ? ขั้นตอนสำคัญควรมีความชัดเจนเพียงพอ - ณ จุดเลือกน้ำหนักคำนวณเมทริกซ์ความแปรปรวนร่วมแบบถ่วงน้ำหนัก (หรือสหสัมพันธ์) รับ PCA จาก SVD ของเมทริกซ์นั้น ทำซ้ำเพื่อให้ได้คะแนนมาก คุณกำลังมองหารายละเอียดของขั้นตอนเหล่านี้หรือไม่?
whuber

ความสุขของฉัน whuber เพื่อแสดงจุดของฉัน n.rows = 20 n.cols = 30 sq = seq (1,600) rast = raster (เมทริกซ์ (sq, nrow = n.rows, byrow = T)) rast2 = raster (เมทริกซ์ (sq, nrow = n.cols)) rast2 ถูกพลิก ถ้าคุณดูแผนที่ของคุณคุณจะเห็นว่าคุณมี 20 คอลัมน์แทน 30 (เซลล์กว้างบนแกน x เพียง 20 แห่งเท่านั้น) แค่อยากช่วย

คุณอาจสนใจที่จะรู้ว่ามีวิธีการใหม่ที่ปรับปรุงใหม่ของวิธีการ GW สำหรับ R รวมถึง GW PCA ที่จะออกในเร็ว ๆ นี้ซึ่งจะนำเสนอใน GISRUK 2013 เมื่อเดือนที่แล้ว
AnserGIS

จากคำอธิบายที่กว้างขวางของ OP ของการวิเคราะห์ที่ต้องการฉันขอแนะนำอย่างยิ่งให้ตรวจสอบวรรณกรรมเกี่ยวกับ "พิกัดหลักของเมทริกซ์เพื่อนบ้าน" (AKA, Eigenvectors ของ Moran) แต่เดิมวิธีการนี้นำเสนอใน 'Borcard D. , & P. ​​Legendre (2002) การวิเคราะห์เชิงพื้นที่ทั้งหมดของข้อมูลเชิงนิเวศน์โดยใช้พิกัดหลักของเมทริกซ์เพื่อนบ้าน การสร้างแบบจำลองเชิงนิเวศน์ 153: 51-68 'และมีประสิทธิภาพมากสำหรับการประเมินข้อมูลข้ามโดเมนเชิงพื้นที่หลายระดับซึ่งเป็นสิ่งที่ GWPCA จะไม่ทำ วิธีนี้ถูกนำไปใช้ในไลบรารีของ spaceMaker และ PCNM R
Jeffrey Evans

คำตอบ:


29

"PCA ถ่วงน้ำหนักทางภูมิศาสตร์" เป็นคำอธิบายที่ดีมาก: ในRโปรแกรมนั้นจะเขียนเอง (ต้องการบรรทัดความคิดเห็นมากกว่าบรรทัดโค้ดจริง)

เริ่มต้นด้วยน้ำหนักเพราะนี่คือส่วนที่ PCA ให้น้ำหนักกับ บริษัท จาก PCA คำว่า "ทางภูมิศาสตร์" หมายถึงน้ำหนักขึ้นอยู่กับระยะทางระหว่างจุดฐานและที่ตั้งข้อมูล มาตรฐาน - แต่ไม่ได้หมายถึง - การถ่วงน้ำหนักเป็นฟังก์ชันเกาส์เซียน; นั่นคือการสลายตัวแบบเอกซ์โปเนนเชียลด้วยระยะห่างกำลังสอง ผู้ใช้จำเป็นต้องระบุอัตราการสลายตัวหรือ - เพิ่มเติมอย่างสังหรณ์ใจ - ระยะทางลักษณะที่จำนวนการสลายตัวคงที่เกิดขึ้น

distance.weight <- function(x, xy, tau) {
  # x is a vector location
  # xy is an array of locations, one per row
  # tau is the bandwidth
  # Returns a vector of weights
  apply(xy, 1, function(z) exp(-(z-x) %*% (z-x) / (2 * tau^2)))
}

PCA ใช้กับความแปรปรวนร่วมหรือเมทริกซ์สหสัมพันธ์ (ซึ่งได้มาจากความแปรปรวนร่วม) จากนั้นที่นี่เป็นฟังก์ชั่นในการคำนวณค่าความแปรปรวนร่วมแบบถ่วงน้ำหนักในวิธีที่มีเสถียรภาพเชิงตัวเลข

covariance <- function(y, weights) {
  # y is an m by n matrix
  # weights is length m
  # Returns the weighted covariance matrix of y (by columns).
  if (missing(weights)) return (cov(y))
  w <- zapsmall(weights / sum(weights)) # Standardize the weights
  y.bar <- apply(y * w, 2, sum)         # Compute column means
  z <- t(y) - y.bar                     # Remove the means
  z %*% (w * t(z))  
}

ความสัมพันธ์นั้นได้มาจากวิธีปกติโดยใช้ค่าเบี่ยงเบนมาตรฐานสำหรับหน่วยการวัดของตัวแปรแต่ละตัว:

correlation <- function(y, weights) {
  z <- covariance(y, weights)
  sigma <- sqrt(diag(z))       # Standard deviations
  z / (sigma %o% sigma)
}

ตอนนี้เราสามารถทำ PCA:

gw.pca <- function(x, xy, y, tau) {
  # x is a vector denoting a location
  # xy is a set of locations as row vectors
  # y is an array of attributes, also as rows
  # tau is a bandwidth
  # Returns a `princomp` object for the geographically weighted PCA
  # ..of y relative to the point x.
  w <- distance.weight(x, xy, tau)
  princomp(covmat=correlation(y, w))
}

(นั่นคือโค้ดที่สามารถเรียกใช้งานได้สุทธิ 10 บรรทัดจนถึงตอนนี้เราจะต้องเพิ่มอีกเพียงหนึ่งอันด้านล่างหลังจากเราอธิบายกริดที่จะทำการวิเคราะห์)


มาแสดงตัวอย่างกับข้อมูลตัวอย่างแบบสุ่มเปรียบเทียบกับที่อธิบายไว้ในคำถาม: ตัวแปร 30 ตัวที่ 550 ตำแหน่ง

set.seed(17)
n.data <- 550
n.vars <- 30
xy <- matrix(rnorm(n.data * 2), ncol=2)
y <- matrix(rnorm(n.data * n.vars), ncol=n.vars)

การคำนวณน้ำหนักทางภูมิศาสตร์มักดำเนินการในชุดของสถานที่ที่เลือกเช่นตามแนวตัดขวางหรือที่จุดของกริดปกติ ลองใช้กริดหยาบเพื่อรับมุมมองเกี่ยวกับผลลัพธ์ ต่อมา - เมื่อเรามั่นใจว่าทุกอย่างทำงานได้และเราได้สิ่งที่ต้องการ - เราสามารถปรับแต่งกริด

# Create a grid for the GWPCA, sweeping in rows
# from top to bottom.
xmin <- min(xy[,1]); xmax <- max(xy[,1]); n.cols <- 30
ymin <- min(xy[,2]); ymax <- max(xy[,2]); n.rows <- 20
dx <- seq(from=xmin, to=xmax, length.out=n.cols)
dy <- seq(from=ymin, to=ymax, length.out=n.rows)
points <- cbind(rep(dx, length(dy)),
                as.vector(sapply(rev(dy), function(u) rep(u, length(dx)))))

มีคำถามว่าข้อมูลใดที่เราต้องการเก็บจาก PCA แต่ละรายการ โดยปกติแล้ว PCA สำหรับnตัวแปรส่งกลับรายการที่เรียงลำดับของnค่าลักษณะเฉพาะและ - ในรูปแบบต่างๆ - รายการที่สอดคล้องกันของnเวกเตอร์ของแต่ละคนความยาวn นั่นคือตัวเลข n * (n + 1) เพื่อทำแผนที่! นำเอาสัญญาณจากคำถามมาแมปค่าลักษณะเฉพาะ สิ่งเหล่านี้ถูกแยกออกมาจากผลลัพธ์ของgw.pcaผ่านทางแอ$sdevททริบิวต์ซึ่งเป็นรายการของค่าลักษณะเฉพาะโดยค่าจากมากไปน้อย

# Illustrate GWPCA by obtaining all eigenvalues at each grid point.
system.time(z <- apply(points, 1, function(x) gw.pca(x, xy, y, 1)$sdev))

สิ่งนี้จะเสร็จสมบูรณ์ในเวลาน้อยกว่า 5 วินาทีในเครื่องนี้ ขอให้สังเกตว่าระยะทางที่มีลักษณะเฉพาะ (หรือ "แบนด์วิดธ์") 1 gw.pcaถูกใช้ในการเรียกร้องให้


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

library("raster")
to.raster <- function(u) raster(matrix(u, nrow=n.cols), 
                                xmn=xmin, xmx=xmax, ymn=ymin, ymx=ymax)
maps <- apply(z, 1, to.raster)
par(mfrow=c(2,2))
tmp <- lapply(maps, function(m) {plot(m); points(xy, pch=19)})

แผนที่

นี่เป็นสี่แผนที่แรกจาก 30 แผนที่แสดงค่าลักษณะเฉพาะที่ใหญ่ที่สุดสี่แห่ง (อย่าตื่นเต้นเกินไปกับขนาดของพวกเขาซึ่งเกิน 1 ในทุกสถานที่จำได้ว่าข้อมูลเหล่านี้ถูกสร้างขึ้นแบบสุ่มทั้งหมดและถ้าพวกเขามีโครงสร้างความสัมพันธ์ใด ๆ เลย - ซึ่งค่าลักษณะเฉพาะขนาดใหญ่ในแผนที่เหล่านี้ดูเหมือนจะบ่งบอก - มันเป็นเพราะโอกาสเพียงอย่างเดียวและไม่ได้สะท้อนอะไร "ของจริง" ที่อธิบายกระบวนการสร้างข้อมูล)

เป็นคำแนะนำในการเปลี่ยนแบนด์วิดธ์ หากมีขนาดเล็กเกินไปซอฟต์แวร์จะบ่นเกี่ยวกับสิ่งแปลกประหลาด (ฉันไม่ได้สร้างในการตรวจสอบข้อผิดพลาดใด ๆ ในการใช้งานกระดูกเปลือยนี้) แต่การลดจาก 1 เป็น 1/4 (และใช้ข้อมูลเดิมเหมือนเดิม) จะให้ผลลัพธ์ที่น่าสนใจ:

แผนที่ 2

สังเกตแนวโน้มของจุดรอบ ๆ ขอบเขตเพื่อให้ค่าลักษณะเฉพาะขนาดใหญ่ผิดปกติ (แสดงในตำแหน่งสีเขียวของแผนที่ด้านซ้ายมือ) ในขณะที่ค่าลักษณะเฉพาะอื่น ๆ จะถูกชดเชยเพื่อชดเชย (แสดงโดยสีชมพูอ่อนในอีกสามแผนที่) . ปรากฏการณ์นี้และรายละเอียดปลีกย่อยอื่น ๆ ของ PCA และการกำหนดน้ำหนักทางภูมิศาสตร์จะต้องมีการทำความเข้าใจก่อนจึงจะสามารถหวังได้ว่าจะตีความรุ่น PCA ที่มีน้ำหนักตามภูมิศาสตร์ได้อย่างน่าเชื่อถือ แล้วมีอีก 30 * 30 = 900 eigenvectors (หรือ "loadings") ที่ต้องพิจารณา ...


1
โดดเด่นตามปกติ @whuber ขอบคุณมาก!
Michael Markieta

1
แค่ต้องการทำให้คุณรู้ว่าในฟังก์ชั่น to.raster คุณต้องมีเมทริกซ์ (u, nrow = n.rows, byrow = TRUE) แทนเมทริกซ์ (u, nrow = n.cols)

1
@cqh ขอบคุณที่ดูรหัสนี้อย่างระมัดระวัง! คุณชี้ไปที่ข้อกังวลที่ชอบด้วยกฎหมาย ฉันจำได้ว่าต้องจัดการกับปัญหานี้ อย่างไรก็ตามฉันคิดว่ารหัสนั้นถูกต้องตามที่เป็นอยู่ หากฉันผสมการเรียงแถว / คอลัมน์เข้าด้วยกันภาพประกอบจะหมดไปอย่างสมบูรณ์ (นั่นเป็นเหตุผลที่ฉันทดสอบด้วยจำนวนแถวและคอลัมน์ที่แตกต่างกัน) ฉันขอโทษสำหรับนิพจน์ที่โชคร้ายnrow=n.colsแต่นั่นเป็นวิธีที่มันได้ผล (ขึ้นอยู่กับวิธีการpointsสร้าง) และฉันไม่ต้องการกลับไปและเปลี่ยนชื่อทุกอย่าง
whuber

14

ปรับปรุง:

ขณะนี้มีแพ็คเกจ R พิเศษที่มีอยู่ใน CRAN - GWmodelซึ่งมี PCA ถ่วงน้ำหนักทางภูมิศาสตร์ท่ามกลางเครื่องมืออื่น ๆ จากเว็บไซต์ของผู้เขียน:

แพ็คเกจ R ใหม่ของเราสำหรับการสร้างแบบจำลองถ่วงน้ำหนักทางภูมิศาสตร์ GWmodel เพิ่งอัปโหลดไปยัง CRAN GWmodel จัดหาวิธีการวิเคราะห์ข้อมูลทางภูมิศาสตร์ในแพ็คเกจเดียวซึ่งรวมถึงสถิติเชิงพรรณนาความสัมพันธ์การถดถอยแบบจำลองเชิงเส้นทั่วไปและการวิเคราะห์องค์ประกอบหลัก แบบจำลองการถดถอยประกอบด้วยข้อมูลต่าง ๆ สำหรับโครงสร้างแบบเกาส์โลจิสติกและปัวซองเช่นเดียวกับการถดถอยสันสำหรับการจัดการกับตัวทำนายที่สัมพันธ์กัน คุณลักษณะใหม่ของแพ็คเกจนี้คือการจัดหาเวอร์ชั่นที่ทนทานของแต่ละเทคนิค - สิ่งเหล่านี้สามารถต้านทานผลกระทบของค่าผิดปกติได้

สถานที่สำหรับการสร้างแบบจำลองสามารถอยู่ในระบบพิกัดที่คาดการณ์ไว้หรือระบุโดยใช้พิกัดทางภูมิศาสตร์ ตัวชี้วัดระยะทางรวมถึง Euclidean, รถแท็กซี่ (แมนฮัตตัน) และ Minkowski รวมถึงระยะทางวงกลมขนาดใหญ่สำหรับสถานที่ที่ระบุโดยพิกัดละติจูด / ลองจิจูด นอกจากนี้ยังมีวิธีการสอบเทียบอัตโนมัติหลายแบบและมีเครื่องมือสร้างแบบจำลองที่มีประโยชน์เพื่อช่วยเลือกจากเครื่องมือทำนายทางเลือก

ตัวอย่างชุดข้อมูลที่มีให้ยังและพวกเขาจะใช้ในเอกสารประกอบในภาพประกอบของการใช้เทคนิคต่างๆ

รายละเอียดเพิ่มเติม INA แสดงตัวอย่างของกระดาษกำลังจะมาถึง


ฉันสงสัยว่าโซลูชัน 'พร้อมใช้งานเสียบอยู่กับข้อมูลของคุณหรือไม่' แต่ฉันหวังว่าจะได้รับการพิสูจน์ว่าผิดเพราะฉันชอบที่จะทดสอบวิธีการนี้กับข้อมูลบางส่วนของฉัน

ตัวเลือกบางอย่างที่ควรพิจารณา:


Marí-Dell'Olmo และเพื่อนร่วมงานใช้การวิเคราะห์ตัวประกอบแบบเบย์เพื่อคำนวณดัชนีการกีดกันพื้นที่เล็ก ๆ ในสเปน:

การวิเคราะห์ปัจจัยแบบเบย์เพื่อคำนวณดัชนีการกีดกันและความไม่แน่นอน Marí-Dell'Olmo M, Martínez-Beneito MA, Borrell C, Zurriaga O, Nolasco A, Domínguez-Berjón MF ระบาดวิทยา 2554 พฤษภาคม 22 (3): 356-64

ในบทความพวกเขาให้ข้อมูลจำเพาะสำหรับโมเดล WinBUGS ที่ดำเนินการจาก R ซึ่งอาจช่วยให้คุณเริ่มต้นได้


adegenetแพคเกจ R ใช้spcaฟังก์ชั่น แม้ว่ามันจะมุ่งเน้นไปที่ข้อมูลทางพันธุกรรม แต่ก็อาจจะใกล้เคียงกับทางออกสำหรับปัญหาของคุณเท่าที่คุณจะได้รับ ไม่ว่าจะโดยใช้แพ็คเกจ / ฟังก์ชั่นนี้โดยตรงหรือแก้ไขโค้ด มีบทความสั้น ๆเกี่ยวกับปัญหาที่จะทำให้คุณพร้อมใช้งาน


นักวิจัยที่Strategic Research Clusterดูเหมือนจะทำงานอย่างแข็งขันในหัวข้อ โดยเฉพาะอย่างยิ่งPaul HarrisและChris Brunsdon (ที่นี่การนำเสนอที่ฉันสะดุด) สิ่งพิมพ์ล่าสุดของ Paul และ Urska ( ข้อความเต็ม ) อาจเป็นทรัพยากรที่มีประโยชน์:

Demšar U, Harris P, Brunsdon C, Fotheringham AS, McLoone S (2012) การวิเคราะห์องค์ประกอบหลักเกี่ยวกับข้อมูลเชิงพื้นที่: ภาพรวม พงศาวดารของสมาคมนักภูมิศาสตร์อเมริกัน

ทำไมคุณไม่ลองติดต่อพวกเขาและถามว่าพวกเขาใช้วิธีแก้ปัญหาอะไรกันแน่? พวกเขาอาจเต็มใจแบ่งปันงานหรือชี้แนะทิศทางที่ดี


Cheng, Q. (2006) การวิเคราะห์องค์ประกอบหลักเชิงพื้นที่และเชิงพื้นที่สำหรับการประมวลผลภาพ IGARSS 2006: 972-975

กระดาษกล่าวถึงการใช้GeoDAS GISระบบ อาจเป็นผู้นำอีกคนหนึ่ง


2
+1 การนำเสนอ Brunsdon เน้นการใช้ PCA เป็นเครื่องมือสำรวจเพื่อค้นหาค่าผิดปกติหลายตัวแปรในพื้นที่ (การใช้งานนี้ให้ความสำคัญในspcaบทความสั้น ๆ ) นั่นเป็นการใช้งานที่ทรงพลังและถูกกฎหมายสำหรับ GWPCA (อย่างไรก็ตามวิธีนี้สามารถปรับปรุงได้มากขึ้นและมากขึ้นในจิตวิญญาณของการวิเคราะห์ข้อมูลเชิงพื้นที่ถ้า PCA ถูกแทนที่ด้วยกระบวนการที่แข็งแกร่งยิ่งขึ้น)
whuber

ดูเหมือนว่าทางเลือกอื่นจะเป็น kernel PCA tribesandclimatechange.org/docs/tribes_450.pdf
Jeffrey Evans

1
ขอบคุณสำหรับข้อมูลที่อัปเดต - GWmodelดูเหมือนว่าเป็นแพคเกจที่ควรซื้อ
whuber
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.