Страница 1 из 1

библиотека ogr/gdal для perl - split by column

Добавлено: 15 сен 2009, 17:19
Анна
добрый день всем!
три дня ломаю голову - переборовала все варинты, но безуспешно, может быть кто-то подскажет решение следующей задачи.
хочу сделать скрипт, который эдробит шейпфайл на отдельные шейпы по некоторому полю (аналог операции split by column например в arcview). Хотела написать именно через gdal :) но не получается :( из-за банальной вещи - не могу сделать список уникальных значения той колонки, по которой дробить.
Тот код, что ниже - работает, но! он дико неэффективный, т.к. перебирает последовательно все строки таблицы, а хотелось бы, чтобы цикл перебирал только уникальные значения, иначе уже для 10000 записей это удовольствие растягивается на минут 7.
Что делать?
Пробовала уже и просто подключать какую-то дополнительную библиотеку для работы с dbf - так там не работает sql запрос group by. вобщем, друзья, посоветуйте как получить уникальные значения для определенной колонки таблицы шейпфайла?

Код: Выделить всё

# information that we need:
$dsname = ".";          # name of the datasource (in this case a directory)
$lname = "cirsium";     # name of the layer
$field = "SPECIES";     # name of the field whose value we need
$lname2 = "test2";

$datasource = Geo::OGR::Open($dsname);
$layer1 = $datasource->Layer($lname);

$osr = new Geo::OSR::SpatialReference;
$osr->SetWellKnownGeogCS('WGS84');
$schema = Geo::OGR::Layer::Schema ($layer1);

$layer1->ResetReading(); 

$counter = Geo::OGR::Layer::GetFeatureCount($layer1);
print "$count\n";

for ($count = 0; $count <= $counter; $count++) {

   $feature = $layer1->GetFeature($count);
   $value = $feature->GetField($field);
   print "$value\n";
   
   $sql = "select * from cirsium where SPECIES = '$value'";
   $layer1 = $datasource->ExecuteSQL($sql);
   $datasource2 = Geo::OGR::Driver('ESRI Shapefile')->Create($dsname) or die;
   $layer2 = $datasource2->CreateLayer({ Name => $value, SRS => $osr, GeometryType => $layer1->GetLayerDefn->GeometryType, Schema =>$schema});
   #$layer1->ResetReading(); 
   while ($feature = $layer1->GetNextFeature()) {  
		$value = $feature->GetField($field);
		print "$value\n";
        $layer2->InsertFeature($feature);   
}
}

Re: библиотека ogr/gdal для perl - split by column

Добавлено: 15 сен 2009, 17:45
Максим Дубинин
я бы все-таки внимательнее посмотрел на внешнюю библиотеку для работы с dbf, типа dbfpy (питон), построил бы индекс уникальных значений, а потом скормил его OGR. Явно это должно быть быстрее, чем 10 тыс sql запросов.

Re: библиотека ogr/gdal для perl - split by column

Добавлено: 15 сен 2009, 21:37
Konstantin Tokar
загрузить всё в postgres не быстрее ли будет?

Re: библиотека ogr/gdal для perl - split by column

Добавлено: 16 сен 2009, 11:46
Анна
спасибо за ответы!
to Konstantin Tokar: да, вот и думаю не перелить ли все в базу... пытаюсть соотнести временные затраты\последующее использование.

to sim: да смотрела! (( проблема в том, что можно подключить библиотеку для xls но тогда dbf надо еще и в xls конвертировать, мне кажется это не очень эффективно.
я уж думала, ну ладно - сделаю через доп. скрипт в R - но и там нету функции group by для dbf-ов. замкнутый круг какой-то.

Re: библиотека ogr/gdal для perl - split by column

Добавлено: 17 сен 2009, 03:20
Максим Дубинин
Анна писал(а):я уж думала, ну ладно - сделаю через доп. скрипт в R - но и там нету функции group by для dbf-ов. замкнутый круг какой-то.
Сделать список уникальных значений в R по dbf-файлу? В два счета. В каком виде тебе нужен этот список в итоге? Просто текст?

Re: библиотека ogr/gdal для perl - split by column

Добавлено: 17 сен 2009, 15:38
Анна
Просто список без заголовка и нумерации, но суть в том что у меня все-таки было какое-то ишью со списком уникал значений из дбфа - толи обрезалось название файла после 8 цифр толи еще какая-то ерунда была.

[Сообщение с мобильного устройства] Изображение

Re: библиотека ogr/gdal для perl - split by column

Добавлено: 18 сен 2009, 03:51
Максим Дубинин
как тебе такой вариант?

Код: Выделить всё

x <- c("one","two","three","four","one","three","six")
as.data.frame(table(x))[,1]
> as.data.frame(table(x))[,1]
[1] four one six three two
Levels: four one six three two

Re: библиотека ogr/gdal для perl - split by column

Добавлено: 21 сен 2009, 15:09
Анна
у меня ошибка вылезает
Error in vector("integer", length) : vector size cannot be NA
In addition: Warning messages:
1: In pd * (as.integer(cat) - 1L) : NAs produced by integer overflow
2: In pd * nl : NAs produced by integer overflow
вот мой код (файл в виде dbf приложила вложением

Код: Выделить всё

inputdir = "Y:\\work\\r\\"
outputdir = "Y:\\work\\r\\1\\"

trainingsets = list.files(path=inputdir, pattern="csv")

for (i in 1:length(trainingsets)) {

	afile = paste(inputdir,trainingsets[i],sep="")
	sheetname = substr(trainingsets[i],1,(nchar(trainingsets[i])-4))
	adata = read.csv(afile,header=F,skip=1)
	adata = as.data.frame(table(adata))[,5] # ошибка
        adata = table(adata$V5) # работает, но не утраивает т.к. нужна только первая колонка без заголовков
	write.table(adata,paste(outputdir,sheetname,".txt",sep=""),sep=",",row.names=FALSE)
	
}
и кстати да - с csv это работает, но нужно обращение к dbf напрямую. Библиотека RODBC не работает с именами файлов более 8 символов.