--packages
: bin/pyspark --packages group:name:version
или комбинировать driver-class-path
и jars
bin/pyspark --driver-class-path $PATH_TO_DRIVER_JAR --jars $PATH_TO_DRIVER_JAR
Эти свойства также могут быть установлены с использованием переменной среды PYSPARK_SUBMIT_ARGS
до запуска экземпляра JVM или с помощью conf/spark-defaults.conf
для установки spark.jars.packages
или spark.jars
/ spark.driver.extraClassPath
. append
: добавить содержимое этого: class: DataFrame
к существующим данным. overwrite
: Перезаписать существующие данные. ignore
: тихо игнорируйте эту операцию, если данные уже существуют. error
(случай по умолчанию): выдать исключение, если данные уже существуют. Усиления или другие мелкозернистые модификации не поддерживаются mode = ...
# You can encode credentials in URI or pass
# separately using properties argument
# of jdbc method or options
url = "jdbc:postgresql://localhost/foobar"
properties = {
"user": "foo",
"password": "bar"
}
DataFrame.write.jdbc
df.write.jdbc(url=url, table="baz", mode=mode, properties=properties)
(подробнее см. pyspark.sql.DataFrameWriter
). Известные проблемы :
--packages
(java.sql.SQLException: No suitable driver found for jdbc: ...
) Предполагая, что для решения проблемы нет несоответствия версии драйвера, вы можете добавить класс driver
в properties
. Например: properties = {
...
"driver": "org.postgresql.Driver"
}
df.write.format("jdbc").options(...).save()
может привести к: java.lang.RuntimeException: org.apache.spark.sql.execution.datasources.jdbc.DefaultSource не позволяет создавать таблицу как выбранную. Решение неизвестно. df._jdf.insertIntoJDBC(url, "baz", True)
sqlContext.read.jdbc
: sqlContext.read.jdbc(url=url, table="baz", properties=properties)
или sqlContext.read.format("jdbc")
: (sqlContext.read.format("jdbc")
.options(url=url, dbtable="baz", **properties)
.load())
Известные проблемы и gotchas :
dbtable
/ table
действительным подзапросом. См. Например: Работает ли искривление предиката с JDBC? Более одного часа для выполнения pyspark.sql.DataFrame.take (4) column
(должно быть IntegeType
), lowerBound
, upperBound
, numPartitions
. Предоставьте список взаимоисключающих предикатов predicates
, по одному для каждого требуемого раздела. --packages
выберите желаемую версию и скопируйте данные со вкладки Gradle в форме compile-group:name:version
, заменяющей соответствующие поля) или Центральный репозиторий Maven : PostgreSQL MySQL Стандартный идентификатор стирания ассоциативного контейнера:
for (auto it = m.cbegin(); it != m.cend() /* not hoisted */; /* no increment */)
{
if (must_delete)
{
m.erase(it++); // or "it = m.erase(it)" since C++11
}
else
{
++it;
}
}
Обратите внимание, что мы действительно хотим, чтобы обычный for
цикл здесь, так как мы модифицируем сам контейнер. Цикл, основанный на диапазоне, должен быть строго зарезервирован для ситуаций, когда мы заботимся только об элементах. Синтаксис RBFL делает это ясным, даже не подвергая контейнер внутри тела цикла.
Редактировать. Pre-C ++ 11, вы не могли стереть константы-константы. Там вы должны сказать:
for (std::map<K,V>::iterator it = m.begin(); it != m.end(); ) { /* ... */ }
Стирание элемента из контейнера не противоречит константе элемента. По аналогии, он всегда был совершенно законным delete p
, где p
является указателем на константу. Константа не ограничивает время жизни; константы в C ++ все еще могут перестать существовать.
Я лично предпочитаю этот шаблон, который немного яснее и проще, за счет дополнительной переменной:
for (auto it = m.cbegin(), next_it = m.cbegin(); it != m.cend(); it = next_it)
{
next_it = it; ++next_it;
if (must_delete)
{
m.erase(it);
}
}
Преимущества этого подхода:
it
и next_it
остаются фиксированными на протяжении всей итерации, что позволяет вам легко добавлять дополнительные инструкции, ссылаясь на них, не зацикляясь на том, будут ли они работать по назначению (за исключением того, что вы не можете использовать it
после его удаления). Короче: «Как удалить с карты во время ее итерации?»
Из GCC map impl (примечание GXX_EXPERIMENTAL_CXX0X):
#ifdef __GXX_EXPERIMENTAL_CXX0X__
// _GLIBCXX_RESOLVE_LIB_DEFECTS
// DR 130. Associative erase should return an iterator.
/**
* @brief Erases an element from a %map.
* @param position An iterator pointing to the element to be erased.
* @return An iterator pointing to the element immediately following
* @a position prior to the element being erased. If no such
* element exists, end() is returned.
*
* This function erases an element, pointed to by the given
* iterator, from a %map. Note that this function only erases
* the element, and that if the element is itself a pointer,
* the pointed-to memory is not touched in any way. Managing
* the pointer is the user's responsibility.
*/
iterator
erase(iterator __position)
{ return _M_t.erase(__position); }
#else
/**
* @brief Erases an element from a %map.
* @param position An iterator pointing to the element to be erased.
*
* This function erases an element, pointed to by the given
* iterator, from a %map. Note that this function only erases
* the element, and that if the element is itself a pointer,
* the pointed-to memory is not touched in any way. Managing
* the pointer is the user's responsibility.
*/
void
erase(iterator __position)
{ _M_t.erase(__position); }
#endif
Пример со старым и новым стилем:
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
using namespace std;
typedef map<int, int> t_myMap;
typedef vector<t_myMap::key_type> t_myVec;
int main() {
cout << "main() ENTRY" << endl;
t_myMap mi;
mi.insert(t_myMap::value_type(1,1));
mi.insert(t_myMap::value_type(2,1));
mi.insert(t_myMap::value_type(3,1));
mi.insert(t_myMap::value_type(4,1));
mi.insert(t_myMap::value_type(5,1));
mi.insert(t_myMap::value_type(6,1));
cout << "Init" << endl;
for(t_myMap::const_iterator i = mi.begin(); i != mi.end(); i++)
cout << '\t' << i->first << '-' << i->second << endl;
t_myVec markedForDeath;
for (t_myMap::const_iterator it = mi.begin(); it != mi.end() ; it++)
if (it->first > 2 && it->first < 5)
markedForDeath.push_back(it->first);
for(size_t i = 0; i < markedForDeath.size(); i++)
// old erase, returns void...
mi.erase(markedForDeath[i]);
cout << "after old style erase of 3 & 4.." << endl;
for(t_myMap::const_iterator i = mi.begin(); i != mi.end(); i++)
cout << '\t' << i->first << '-' << i->second << endl;
for (auto it = mi.begin(); it != mi.end(); ) {
if (it->first == 5)
// new erase() that returns iter..
it = mi.erase(it);
else
++it;
}
cout << "after new style erase of 5" << endl;
// new cend/cbegin and lambda..
for_each(mi.cbegin(), mi.cend(), [](t_myMap::const_reference it){cout << '\t' << it.first << '-' << it.second << endl;});
return 0;
}
печатает:
main() ENTRY
Init
1-1
2-1
3-1
4-1
5-1
6-1
after old style erase of 3 & 4..
1-1
2-1
5-1
6-1
after new style erase of 5
1-1
2-1
6-1
Process returned 0 (0x0) execution time : 0.021 s
Press any key to continue.
Предполагая, что C ++ 11, это тело цикла с одним слоем, если это соответствует вашему стилю программирования:
using Map = std::map<K,V>;
Map map;
// Erase members that satisfy needs_removing(itr)
for (Map::const_iterator itr = map.cbegin() ; itr != map.cend() ; )
itr = needs_removing(itr) ? map.erase(itr) : std::next(itr);
Пара других незначительных изменений стиля:
Map::const_iterator
), когда это возможно / удобно, используя auto
. using
для типов шаблонов, чтобы сделать вспомогательные типы (Map::const_iterator
) проще читать / поддерживать. Довольно грустно, а? Обычно я делаю это, создавая контейнер итераторов вместо удаления во время обхода. Затем прокрутите контейнер и используйте map.erase ()
std::map<K,V> map;
std::list< std::map<K,V>::iterator > iteratorList;
for(auto i : map ){
if ( needs_removing(i)){
iteratorList.push_back(i);
}
}
for(auto i : iteratorList){
map.erase(*i)
}
for (int i = 0; i < v.size(); i++)
. Здесь мы должны сказатьv[i]
внутри цикла, т. Е. Мы должны явно указать контейнер. RBFL, с другой стороны, вводит переменную цикла, которая непосредственно используется в качестве значения, и поэтому внутри цикла не требуется знание контейнера. Это ключ к предполагаемому использованию циклов RBFL для циклов, которые not i> должны знать о контейнере. Стирание - это полная противоположная ситуация, когда речь идет о контейнере. – Kerrek SB 23 November 2011 в 00:41it = v.erase(it);
(нет++
). Это никогда не повторится, обещание. – Kerrek SB 23 November 2011 в 00:43it = v.erase(it);
теперь тоже работает для карт. То есть, ассоциация erase () on all i> теперь возвращает следующий итератор. Таким образом, старый kludge, который потребовал post-increment ++ в delete (), больше не нужен. Это (если это правда) - это хорошая вещь, поскольку kludge полагался на магию с переопределенным постом-инкрементом внутри функции, «фиксированную». новичкам-сопровождающим, чтобы получить прирост из вызова функции, или поменять его на предустановление », потому что это всего лишь вещь стиля» и т. д. – Dewi Morgan 30 January 2015 в 00:11