QGIS를 사용하여 500 CSV 파일을 효율적이고 쉽게 재 투영하는 방법은 무엇입니까?


11

내 질문은이 사이트의 일부 오래된 질문과 유사합니다.

qgis로 가져 와서 변환하는 CSV 파일 (지리 좌표) 이 많이 있으며 일반적인 방법은 가장 길지 않습니다 (너무 길다).

거의 500 개의 CSV 파일 (wgs84 좌표)이 있으며 이것이 내가하고 싶은 일입니다.

  1. 모든 CSV 파일을 한 번에 QGIS로 가져 오기
  2. 그들을 투영
  3. CSV 파일로 내보내기 (다시)하지만 좌표가 다른 경우 (UTM33N으로 변환)

파이썬 콘솔 을 사용하는 방법을 이해하려고 노력하고 있지만 계속 움직이지 않습니다.

누구나 단계별로 달성하는 방법을 설명해 줄 수 있습니까?


아래 내 답변을 참조하십시오. 문제는 이미 해결되고 설명되었습니다
Generic Wevers

2
그리고 왜 마크가 표시된 것과 중복됩니까? OP가 pyqgis를 배우려고 시도하고 굵은 글씨를 고려하면 Python을 사용하는 방법 일 수 있습니다.
nickves

질문을 지정하십시오. QGIS에 수동으로로드하지 않겠습니까? 다른 형식으로 변환 하시겠습니까? 질문이 정확히 무엇입니까?
bugmenot123

QGIS 2. 프로젝트에 하나 개의 프로세스 1. 가져 오기 모든 파일 그들 CSV로하지만 UTM 좌표를 모두 다시 내보낼 3
라켈 리베

cat * .csv> one_file.csv (또는 동등한 Windows 항목)는 모든 csv 파일을 하나로 결합합니다. 500은 정말 큰 숫자가 아닙니다 :-)
John Powell

답변:


15

QGIS 의 Python 콘솔 에서 csv 파일을 재 투영하려는 경우 다음 스크립트를 사용할 수 있습니다. 주석에서 언급 한 세 가지 경로 만 변경하면됩니다.

기본적으로 스크립트는 csv 파일을 shapefile로 QGIS로 가져옵니다 (기하학적 필드의 이름이 X및 이라고 가정 Y). 그런 다음 사용 qgis:reprojectlayer하고 qgis:fieldcalculator로부터 알고리즘 처리 툴박스 재 투영하고 업데이트하도록 X하고 Y새로운 좌표 필드. 그런 다음이를 폴더에 저장하고 지정한 경로에 csv 파일로 변환합니다. 결국 모양 파일과 CSV 파일을 별도의 폴더에 업데이트했습니다.

import glob, os, processing

path_to_csv = "C:/Users/You/Desktop/Testing//"  # Change path to the directory of your csv files
shape_result = "C:/Users/You/Desktop/Testing/Shapefile results//"  # Change path to where you want the shapefiles saved

os.chdir(path_to_csv)  # Sets current directory to path of csv files
for fname in glob.glob("*.csv"):  # Finds each .csv file and applies following actions
        uri = "file:///" + path_to_csv + fname + "?delimiter=%s&crs=epsg:4326&xField=%s&yField=%s" % (",", "x", "y")
        name = fname.replace('.csv', '')
        lyr = QgsVectorLayer(uri, name, 'delimitedtext')
        QgsMapLayerRegistry.instance().addMapLayer(lyr)  # Imports csv files to QGIS canvas (assuming 'X' and 'Y' fields exist)

crs = 'EPSG:32633'  # Set crs
shapefiles = QgsMapLayerRegistry.instance().mapLayers().values()  # Identifies loaded layers before transforming and updating 'X' and 'Y' fields
for shapes in shapefiles:
        outputs_0 = processing.runalg("qgis:reprojectlayer", shapes, crs, None)
        outputs_1 = processing.runalg("qgis:fieldcalculator", outputs_0['OUTPUT'], 'X', 0, 10, 10, False, '$x', None)
        outputs_2 = processing.runalg("qgis:fieldcalculator", outputs_1['OUTPUT_LAYER'], 'Y', 0, 10, 10, False, '$y', shape_result + shapes.name())

os.chdir(shape_result)  # Sets current directory to path of new shapefiles
for layer in glob.glob("*.shp"):  # Finds each .shp file and applies following actions
        new_layer = QgsVectorLayer(layer, os.path.basename(layer), "ogr")
        new_name = layer.replace('.shp', '')
        csvpath = "C:/Users/You/Desktop/Testing/CSV results/" + new_name + ".csv"  # Change path to where you want the csv(s) saved
        QgsVectorFileWriter.writeAsVectorFormat(new_layer, csvpath, 'utf-8', None, "CSV")   

도움이 되었기를 바랍니다!


2
좋은 답변-당신은 모든 것을 가지고 있습니다!. 신경 쓰지 않아도되는 한 가지 질문 : 파이썬 콘솔에서 작업을하더라도 QgsMapLayerRegistry에서 레이어를 추가 / 제거해야합니까?
nickves

1
@ nickves-하하 많은 감사 친구! 흠 레이어를 추가 / 제거 할 필요가 없을 수도 있습니다 (스크립트를 크게 줄일 수 있다고 확신합니다). 나는 전문가가 아니지만 나중에 테스트하고 다시 연락 드리겠습니다. 더 깔끔한 스크립트를 제공 할 수 없다면 답으로 게시해야합니다. :)
Joseph

@ nickves-당신의 제안 친구에게 다시 한 번 감사드립니다! 두 번째로 레이어를 추가 / 제거하지 않도록 코드가 편집되었습니다. :)
Joseph

@RaquelRibeiro-가장 환영합니다! 도움이되어서 기뻤습니다 :)
Joseph

@Joseph 다시 질문해도 될까요? 14, 15 행에서 숫자 0, 10, 10은 정확히 무엇을 정의하고 있습니까? (출력 좌표가 오른쪽에 너무 많은 0을 가지고 있고 그것을 최소화하고 싶습니다)
Raquel Ribeiro

8

WGS84에 "lon lat"이 포함 된 공백으로 구분 된 파일을 UTM33N으로 변환하는 빠른 솔루션이지만 다른 데이터는 얻지 못합니다.

#!/bin/bash
#
for i in $( ls *.csv ); do
    gdaltransform -s_srs EPSG:4326 -t_srs EPSG:32633 < ${i} > utm${i}
done

그것은 작동하고 데이터의 순서를 유지하므로 설명 데이터를 좌표와 결합하기 위해 awk를 사용하는 다른 루프?

편집하다. 아래의 지저분한 의견으로 인해 대신 여기에서 답변을 편집하겠습니다.

다음 스크립트는 여러 csv 파일을 읽고 각 파일에 새 좌표 열을 추가하는 작업을 수행해야합니다.

#!/bin/bash
#
for i in $( ls *.csv ); do
 paste -d',' ${i} <(awk -v OFS="," -F " " 'NR>1 {print $1 " " $2}' ${i} | gdaltransform -s_srs EPSG:4326 -t_srs EPSG:32633 | awk '{gsub(" ",",",$0); print $0}' | /usr/local/bin/sed "1i\X,Y,Z") > utm${i}
#
 #paste -d',' ${i} <(awk -v OFS="," -F " " 'NR>1 {print $1 " " $2}' ${i} | gdaltransform -s_srs EPSG:4326 -t_srs EPSG:32633 | awk '{gsub(" ",",",$0); print $0}' |sed "1i\X,Y,Z") > utm${i}
#
done

OSX에서는 최신 (2009) 버전의 sed를 설치하고 루프에서 주석 처리되지 않은 첫 번째 라인을 사용해야합니다. Linux의 경우 첫 번째 주석을 달고 두 번째를 사용하십시오. [조정 -F " "예하여 CSV 파일의 구분자의 포맷에 따라 -F ","콤마 위해 분리. 또한 고도 변환은 지오이드가 아닌 타원체 로 변환되므로 높이를 적절히 변환해야합니다.


방금 전에 비슷한 것을하고 내 블로그에 솔루션을 게시하는 것을 기억했습니다. Mac 용으로 작성되었지만 bash 기반입니다. 가장 큰 차이점은 게시물 끝에서 다루는 OS X의 sed 문제입니다. mercergeoinfo.blogspot.se/2014/01/…
mercergeoinfo

마지막 코멘트는 약간 지저분했다. 위의 bash 스크립트에서이 행을 사용하여 모든 파일을 반복 paste -d',' ${i} <(awk -v OFS="," -F " " 'NR>1 {print $1 " " $2}' ${i} | gdaltransform -s_srs EPSG:4326 -t_srs EPSG:32633 | awk '{gsub(" ",",",$0); print $0}' | /usr/local/bin/sed "1i\X,Y,Z") > utm${i}하십시오. OSX를 사용하지 않는 경우 / usr / local / sed를 sed로 바꾸십시오. 위의 줄에서 가정하는 것처럼 csv 파일이 공백으로 구분 된 경우 이상적이지 않지만 작동합니다. 쉼표를 구분 한 경우 다음과 같이 변경하십시오 -F " ".-F ","
mercergeoinfo

왜 업데이트 된 코드가 주석에 있고 위의 답변을 업데이트하지 않았는지 궁금합니다. 주석의 코드는 실제로 읽기가 어렵습니다. 답변 아래에 수정 링크가 있습니까?
Miro

그렇습니다.하지만 실제로는 추가 업데이트가 아닙니다. 꽤 지저분합니다. 원래 답변을 업데이트해야한다고 생각합니다. 감사합니다
mercergeoinfo

7

qgis 또는 OGR을 사용하는 것은 이것을 과도하게 사용합니다. python csv writer 및 몇 가지 표준 라이브러리 트릭과 결합 된 ( https://pypi.python.org/pypi/pyproj )를
사용하십시오 . 이것 이외의 다른 것을 설치할 필요는 없습니다 ! pyprojpyproj

import csv
import pyproj
from functools import partial
from os import listdir, path

#Define some constants at the top
#Obviously this could be rewritten as a class with these as parameters

lon = 'lon' #name of longitude field in original files
lat = 'lat' #name of latitude field in original files
f_x = 'x' #name of new x value field in new projected files
f_y = 'y' #name of new y value field in new projected files
in_path = u'D:\\Scripts\\csvtest\\input' #input directory
out_path = u'D:\\Scripts\\csvtest\\output' #output directory
input_projection = 'epsg:4326' #WGS84
output_projecton = 'epsg:32633' #UTM33N

#Get CSVs to reproject from input path
files= [f for f in listdir(in_path) if f.endswith('.csv')]

#Define partial function for use later when reprojecting
project = partial(
    pyproj.transform,
    pyproj.Proj(init=input_projection),
    pyproj.Proj(init=output_projecton))

for csvfile in files:
    #open a writer, appending '_project' onto the base name
    with open(path.join(out_path, csvfile.replace('.csv','_project.csv')), 'wb') as w:
        #open the reader
        with open(path.join( in_path, csvfile), 'rb') as r:
            reader = csv.DictReader(r)
            #Create new fieldnames list from reader
            # replacing lon and lat fields with x and y fields
            fn = [x for x in reader.fieldnames]
            fn[fn.index(lon)] = f_x
            fn[fn.index(lat)] = f_y
            writer = csv.DictWriter(w, fieldnames=fn)
            #Write the output
            writer.writeheader()
            for row in reader:
                x,y = (float(row[lon]), float(row[lat]))
                try:
                    #Add x,y keys and remove lon, lat keys
                    row[f_x], row[f_y] = project(x, y)
                    row.pop(lon, None)
                    row.pop(lat, None)
                    writer.writerow(row)
                except Exception as e:
                    #If coordinates are out of bounds, skip row and print the error
                    print e

나는 포스터가 파이썬에 매우 경험이 없다는 것을 알고 있습니다. QGIS를 정기적으로 사용하지 않으므로 해당 플랫폼에 대한 경험이 많은 사람이 파이썬이 설치된 위치를 설명 할 수 있습니까? 포스터는 이것을 독립형 스크립트로 만들고 아마도 IDLE에서 실행해야합니다. 현재 설치되어 있지 않으므로 pyproj포스터 용으로 별도로 설치 해야하는지 또는 이미 설치되어 있는지 알 수 없습니다 .
blord-castillo 님이

1
전에 부분 기능을 사용한 적이 없습니다. 지금부터 할 것입니다. +1
nickves

4

파이썬이 필요하지 않습니다. 명령 행과 ogr2ogr을 사용하십시오. 귀하의 경우 가장 중요한 것은 -t_srs srs_def 매개 변수입니다.

이것은 이미 설명 이 대답나는 모양 파일에 X와 엑셀 파일, Y 열을 변환 할 수 있습니까?

업데이트 완전한 코드를 작성할 시간이 없습니다. 그러나 문제는 생각보다 파이썬에서 조금 더 많은 코드가 필요하다는 것입니다.

주요 문제는 CSV 파일 작업이 shapefile을 사용하는 것만 큼 편안하지 않다는 것입니다. 따라서 먼저 csv를 VRT 파일이 필요한 모양으로 변환해야합니다. 이것은 첫 번째 링크에서 설명됩니다. 여기에 vrt 파일을 자동으로 생성하는 파일을 통해 python 스크립트를 작성해야합니다.

이것은 내가 직접 사용한 스크립트입니다. 그것이 효과가 있는지 테스트해야합니다. 이미 WGS 84에서 UTM 33N으로의 변환을 포함했습니다.

from os import listdir, stat, mkdir, system
path = "your path here"
out_path = "your output path here"
files = filter(listdir(path), '*.csv') #for Python 3.x
# files= [f for f in listdir(path) if f.endswith('.csv')] #for Python 2.7

for x in range(len(files)):
    name = files[x].replace('.csv', '')
    # 2. create vrt file for reading csv
    outfile_path1 = out_path + name + '.vrt'
    text_file = open(outfile_path1, "w")
    text_file.write('<OGRVRTDataSource> \n')
    text_file.write('    <OGRVRTLayer name="' + str(name) + '"> \n')
    text_file.write('        <SrcDataSource relativeToVRT="1">' + name + '.csv</SrcDataSource> \n')
    text_file.write('        <GeometryType>wkbPoint</GeometryType> \n')
    text_file.write('        <LayerSRS>WGS84</LayerSRS> \n')
    text_file.write('        <GeometryField encoding="PointFromColumns" x="Lon" y="Lat"/> \n')
    text_file.write('        <Field name="Name" src="Name" type="String" /> \n')
    text_file.write('    </OGRVRTLayer> \n')
    text_file.write('</OGRVRTDataSource> \n')
    # 3. convert csv/vrt to point shapefile
    outfile_path2 = out_path + name + '.shp'
    command = ('ogr2ogr -f "ESRI Shapefile" -t_srs EPSG:32633' + outfile_path2 + ' ' +  outfile_path1)
    system(command)

csv 파일에 따라 Field name , src , xy 에 대한 매개 변수를 조정해야 합니다.

업데이트 2

몇 가지 생각을 한 후 QGIS를 왜 사용하고 싶습니까? 당신은 같은 파이썬 스크립트를 사용할 수있는 직접 UTM에 WGS에서 좌표를 변환 할 수 있습니다. 이 경우에는 간단한 열린 CSV, 좌표 읽기, 좌표 변환 및 새 파일로 저장됩니다.


나는 이것이 내가 찾고있는 것이 아니라고 생각합니다 ... 거의 500 csv 파일 (wgs84 좌표)을 가지고 있으며 이것은 내가하고 싶은 일입니다 : 1. 모든 csv 파일을 q gis로 한 번에 가져옵니다 2. 프로젝트 3. CSV 파일로 내보내기 (다시)하지만 다른 좌표로 (utm33N으로 변환)
Raquel Ribeiro

나는 그것을 할 수있는 배치 프로세스 또는 somethig가 필요하다고 생각합니다 ...
Raquel Ribeiro

4
근데 왜 그렇게하고 싶니? 1. qgis없이 명령 행에서 동일한 내용 (설명한 내용)을 수행 할 수 있습니다. 2. 배치 모드에서이 작업을 수행 할 수 있습니다. 3. 파이썬에서는 거의 동일합니다. 또한 ogr2ogr
Generic Wevers

2
명령 줄을 사용하는 "간단하게"는 실제로 답이 아닙니다. 어떻게 해야할지 모르겠다면 명령 행을 사용하기가 쉽지 않습니다. 그리고 나는 실제로 링크 된 답변에서 해결책을 찾을 수 없습니다. 왜 가난한 사람에게 ogr2ogr을 사용한 예제 배치를 제공하는 것이 좋을까요?
Bernd V.

1
좋아, 1. gis.stackexchange.com/help/how-to-ask를 읽을 수 있습니다 . 그 후 5 분의 Google 검색 후에는 질문이 매우 잘 연구되지 않았으며 이미 주어진 답변으로 해결할 수 있음을 인정합니다. 2. 그래도 해결할 수 없으면 모두 기꺼이 도와 줄 것입니다. 그러나 나는 좋은 사람이므로 몇 가지 더 힌트를 줄 것입니다.
Generic Wevers
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.