Я считаю, что этот ответ более корректен, чем другие ответы здесь:
from sklearn.tree import _tree
def tree_to_code(tree, feature_names):
tree_ = tree.tree_
feature_name = [
feature_names[i] if i != _tree.TREE_UNDEFINED else "undefined!"
for i in tree_.feature
]
print "def tree({}):".format(", ".join(feature_names))
def recurse(node, depth):
indent = " " * depth
if tree_.feature[node] != _tree.TREE_UNDEFINED:
name = feature_name[node]
threshold = tree_.threshold[node]
print "{}if {} <= {}:".format(indent, name, threshold)
recurse(tree_.children_left[node], depth + 1)
print "{}else: # if {} > {}".format(indent, name, threshold)
recurse(tree_.children_right[node], depth + 1)
else:
print "{}return {}".format(indent, tree_.value[node])
recurse(0, 1)
Это выводит действительную функцию Python. Вот пример вывода для дерева, которое пытается вернуть свой вход, число от 0 до 10.
def tree(f0):
if f0 <= 6.0:
if f0 <= 1.5:
return [[ 0.]]
else: # if f0 > 1.5
if f0 <= 4.5:
if f0 <= 3.5:
return [[ 3.]]
else: # if f0 > 3.5
return [[ 4.]]
else: # if f0 > 4.5
return [[ 5.]]
else: # if f0 > 6.0
if f0 <= 8.5:
if f0 <= 7.5:
return [[ 7.]]
else: # if f0 > 7.5
return [[ 8.]]
else: # if f0 > 8.5
return [[ 9.]]
Вот несколько камней преткновения, которые я вижу в других ответах:
tree_.threshold == -2
для определения того, является ли узел листом, не является хорошей идеей. Что, если это реальный узел решения с порогом -2? Вместо этого вы должны посмотреть на tree.feature
или tree.children_*
. features = [feature_names[i] for i in tree_.feature]
выходит из строя с моей версией sklearn, потому что некоторые значения tree.tree_.feature
равны -2 (специально для листовых узлов). Вы можете преобразовать его в timedelta с точностью до дня. Чтобы извлечь целочисленное значение дней, вы разделите его на timedelta одного дня.
>>> x = np.timedelta64(2069211000000000, 'ns')
>>> days = x.astype('timedelta64[D]')
>>> days / np.timedelta64(1, 'D')
23
Или, как предположил @PhillipCloud, просто days.astype(int)
, поскольку timedelta
- всего лишь 64-битное целое число, которое ('D'
, 'ns'
, ...).
Вы можете найти больше об этом здесь .
g3]
Предположим, у вас есть серия timedelta:
import pandas as pd
from datetime import datetime
z = pd.DataFrame({'a':[datetime.strptime('20150101', '%Y%m%d')],'b':[datetime.strptime('20140601', '%Y%m%d')]})
td_series = (z['a'] - z['b'])
. Один из способов конвертировать этот timedelta-столбец или серию - это передать его объекту Timedelta (pandas 0.15.0+), а затем извлечь дни из объект:
td_series.astype(pd.Timedelta).apply(lambda l: l.days)
Другой способ состоит в том, чтобы вывести серию как timedelta64 в днях, а затем передать ее как int:
td_series.astype('timedelta64[D]').astype(int)
Используйте dt.days
, чтобы получить атрибут days как целые числа.
Например:
In [14]: s = pd.Series(pd.timedelta_range(start='1 days', end='12 days', freq='3000T'))
In [15]: s
Out[15]:
0 1 days 00:00:00
1 3 days 02:00:00
2 5 days 04:00:00
3 7 days 06:00:00
4 9 days 08:00:00
5 11 days 10:00:00
dtype: timedelta64[ns]
In [16]: s.dt.days
Out[16]:
0 1
1 3
2 5
3 7
4 9
5 11
dtype: int64
В более общем плане - вы можете использовать кнопку .components
для доступа к уменьшенной форме timedelta
.
In [17]: s.dt.components
Out[17]:
days hours minutes seconds milliseconds microseconds nanoseconds
0 1 0 0 0 0 0 0
1 3 2 0 0 0 0 0
2 5 4 0 0 0 0 0
3 7 6 0 0 0 0 0
4 9 8 0 0 0 0 0
5 11 10 0 0 0 0 0
Теперь, чтобы получить атрибут hours
:
In [23]: s.dt.components.hours
Out[23]:
0 0
1 2
2 4
3 6
4 8
5 10
Name: hours, dtype: int64