Я думаю, что вы можете использовать np.where
, чтобы найти, где df.day
равно 20, и получить значение 28, 29 и 30, в зависимости от случая, это на самом деле, где df.day
равно df.month_total_days
, за исключением случаев, когда df.month_total_days
больше 30, поэтому вы можете использовать, например, pd.clip_upper
, чтобы иметь 30 вместо любого значения, превышающего
.
import numpy as np
df['is_payday'] = np.where( (df.day == 20) |
(df.day == df.month_total_days.clip_upper(30), 1, 0)
Я думаю проблема, которую Вы имеете, то, потому что Вы пытаетесь создать универсальный тип и затем создать список того универсального типа. Вы могли выполнить то, что Вы пытаетесь сделать, выходя из типов данных, которые Вы пытаетесь поддерживать, сказать как элемент IData и затем создать Ваш MyData, универсальный с ограничением IData. Оборотная сторона к этому была бы то, что необходимо будет создать собственные типы данных для представления всех примитивных типов данных, которые Вы используете (строка, интервал, плавание, долго). Это могло бы выглядеть примерно так:
public class MyData<T, C>
where T : IData<C>
{
public T Data { get; private set; }
public MyData (T value)
{
Data = value;
}
}
public interface IData<T>
{
T Data { get; set; }
void SomeMethod();
}
//you'll need one of these for each data type you wish to support
public class MyString: IData<string>
{
public MyString(String value)
{
Data = value;
}
public void SomeMethod()
{
//code here that uses _data...
Console.WriteLine(Data);
}
public string Data { get; set; }
}
и затем Вы - реализация, было бы что-то как:
var myData = new MyData<MyString, string>(new MyString("new string"));
// Could be MyString, MyInt, ...
myData.Data.SomeMethod();
это - немного больше работы, но Вы получаете функциональность, для которой Вы шли.
ОБНОВЛЕНИЕ: удаляют SomeMethod из Вашего интерфейса и просто делают это
SomeMethod(myData.Data.Data);
Просто используйте ArrayList и забудьте эти MyData<T>
тип.
ArrayList myStuff = getStuff();
float x = myStuff.OfType<float>().First();
SomeMethod(x);
string s = myStuff.OfType<string>().First();
SomeMethod(s);
проблема с MyData<T>
состоит в том, что Вы ожидаете, что компилятор проверит тип, который только известен во времени выполнения. Компиляторы проверяют типы, которые известны во время компиляции.
Вы не можете сделать этого способ, которым Вы хотите.
, Когда экземпляр универсального класса инициализируется, он связывается с конкретным типом. Так как Вы хотите держать объекты различных типов в Вашем списке, необходимо создать экземпляр, связанный с наименее общим знаменателем — в случае, это - Объект.
Однако, который означает, что Свойство данных теперь возвратит объект текстового объекта. Компилятор не может вывести фактический тип данных во время компиляции, таким образом, он может выбрать соответствующее SomeMethod
перегрузка.
необходимо или обеспечить перегрузку SomeMethod
, который берет Объект в качестве параметра, или удалите требование для содержания отличающийся такие различные типы в наборе.
Или можно пойти со стандартом IEnumerable
набор (как Массив) и использовать OfType<>
дополнительный метод для получения подмножества набора конкретного типа.
В этом случае Вам нужно MyData<object>
, так как это - единственная вещь, которую имеют общего те типы.
Можно создать универсальную обертку для SomeMethod
и проверить на тип универсального аргумента, затем делегировать к соответствующему методу.
public void SomeMethod<T>(T value)
{
Type type = typeof(T);
if (type == typeof(int))
{
SomeMethod((int) (object) value); // sadly we must box it...
}
else if (type == typeof(float))
{
SomeMethod((float) (object) value);
}
else if (type == typeof(string))
{
SomeMethod((string) (object) value);
}
else
{
throw new NotSupportedException(
"SomeMethod is not supported for objects of type " + type);
}
}
Предложенные подстановочные знаки некоторое время назад здесь . Закрытый как "не зафиксирует": (
Дженерики позволяют Вам определять один тип для целого списка при создании списка например, список для хранения интервала был бы создан как это
var myData = new MyData<int>();
, Если Вы хотите сохранить несколько типов в том же универсальном списке, можно определить тип общей базы или интерфейс для тех типов. К сожалению, в Вашем случае единственный тип общей базы для типов, которые Вы хотите сохранить, был бы объектом.
var myData = new MyData<object>();
, Но можно просто использовать неуниверсальный список для того, чтобы хранить объекты.
Наследуйте MyData<T>
от недженерика MyData
класс и составьте список этого.
Таким образом, Вы не можете автоматически разрешить перегрузку. Необходимо сделать это вручную.
abstract class MyData {
protected abstract object GetData();
protected abstract Type GetDataType();
public object Data {
get { return GetData(); }
}
public Type DataType {
get { return GetDataType(); }
}
}
class MyData<T> : MyData {
protected override object GetData() { return Data; }
protected override Type GetDataType() { return typeof(T); }
public new T Data {
get { ... }
}
}