Большинство ответов здесь не могут объяснить, какова фактическая проблема с разрезанием. Они объясняют только доброкачественные случаи нарезки, а не предательские. Предположим, как и другие ответы, что вы имеете дело с двумя классами A
и B
, где B
получает (публично) из A
.
В этой ситуации C ++ позволяет вам передать экземпляр оператора B
в A
, а также в конструктор копирования. Это работает, потому что экземпляр B
может быть преобразован в const A&
, а именно, какие операторы присваивания и конструкторы-копии ожидают, что их аргументы будут.
B b;
A a = b;
Ничего плохого в этом нет - вы попросили экземпляр A
, который является копией B
, и это именно то, что вы получаете. Конечно, a
не будет содержать некоторых членов b
, но как это сделать? В конце концов, это A
, а не B
, поэтому даже не слышал об этих членах, не говоря уже о возможности их хранения.
B b1;
B b2;
A& a_ref = b2;
a_ref = b1;
//b2 now contains a mixture of b1 and b2!
Вы можете подумать, что b2
будет копией b1
впоследствии. Но, увы, это не так! Если вы проверите его, вы обнаружите, что b2
- это франкенштейновское существо, сделанное из некоторых кусков b1
(куски, которые B
наследует от A
), и некоторые фрагменты b2
(куски что только B
содержит). Ой!
Что случилось? Ну, C ++ по умолчанию не обрабатывает операторы присваивания как virtual
. Таким образом, строка a_ref = b1
вызовет оператор присваивания A
, а не номер B
. Это связано с тем, что для не виртуальных функций объявленный тип (который является A&
) определяет, какая функция вызывается, в отличие от фактического типа (который был бы B
, поскольку a_ref
ссылается на экземпляр B
). Теперь оператор присваивания A
явно знает только о членах, объявленных в A
, поэтому он будет копировать только те, оставляя члены, добавленные в B
без изменений.
Присвоение только части объекта обычно имеет мало смысла, но, к сожалению, C ++ не предусматривает встроенного способа запретить это. Вы можете, однако, бросить свои собственные. Первый шаг - сделать оператор присваивания виртуальным . Это гарантирует, что он всегда является оператором присваивания фактического типа, который вызывается, а не объявленным типом. Второй шаг - использовать dynamic_cast
, чтобы убедиться, что назначенный объект имеет совместимый тип. Третий шаг - выполнить фактическое присвоение в члене (protected!) assign()
, так как B
assign()
, вероятно, захочет использовать A
's assign()
для копирования A
членов .
class A {
public:
virtual A& operator= (const A& a) {
assign(a);
return *this;
}
protected:
void assign(const A& a) {
// copy members of A from a to this
}
};
class B : public A {
public:
virtual B& operator= (const A& a) {
if (const B* b = dynamic_cast<const B*>(&a))
assign(*b);
else
throw bad_assignment();
return *this;
}
protected:
void assign(const B& b) {
A::assign(b); // Let A's assign() copy members of A from b to this
// copy members of B from b to this
}
};
Обратите внимание, что для чистого удобства B
operator=
ковариантно переопределяет возвращаемый тип, поскольку он знает, что он возвращает экземпляр B
.
В pandas 0.17.0
convert_objects
вызывают предупреждение:
FutureWarning: convert_objects устарел. Используйте специальные преобразователи данных типа pd.to_datetime, pd.to_timedelta и pd.to_numeric.
blockquote>Вы можете использовать метод
pd.to_numeric
и применить его для кадра данных с argcoerce
.df1 = df.apply(pd.to_numeric, args=('coerce',))
или может быть более подходящим образом:
df1 = df.apply(pd.to_numeric, errors='coerce')
EDIT
Этот метод действителен только для версии pandas> =
0.17.0
, from docs Что нового в pandas 0.17.0 :pd.to_numeric - это новая функция, которая может принуждать строки к числам (возможно, с принуждением) (GH11133)
blockquote>
Вы можете просто использовать pd.to_numeric
и установить ошибку на coerce
без использования apply
df['foo'] = pd.to_numeric(df['foo'], errors='coerce')
Используйте метод серии convert_objects
(и convert_numeric
):
In [11]: s
Out[11]:
0 103.8
1 751.1
2 0.0
3 0.0
4 -
5 -
6 0.0
7 -
8 0.0
dtype: object
In [12]: s.convert_objects(convert_numeric=True)
Out[12]:
0 103.8
1 751.1
2 0.0
3 0.0
4 NaN
5 NaN
6 0.0
7 NaN
8 0.0
dtype: float64
Примечание: это также доступно как метод DataFrame.
Сначала замените все строковые значения на None
, чтобы пометить их как отсутствующие значения, а затем преобразовать их в float.
df['foo'][df['foo'] == '-'] = None
df['foo'] = df['foo'].astype(float)
0.17.0
версии pandas – Anton Protopopov 30 November 2015 в 08:44