научите меня, как это сделать в панде? - PullRequest
0 голосов
/ 08 сентября 2018

Я изо всех сил пытаюсь преобразовать электронную таблицу в Python, используя фреймы данных Pandas.

У меня есть необработанные данные:

Date        Temperature
12/4/2003   100
12/5/2003   101
12/8/2003   100
12/9/2003   102
12/10/2003  101
12/11/2003  100
12/12/2003  99
12/15/2003  98
12/16/2003  97
12/17/2003  96
12/18/2003  95
12/19/2003  96
12/22/2003  97
12/23/2003  98
12/24/2003  99
12/26/2003  100
12/29/2003  101

В электронной таблице я следую тренду, основанному на мониторе%. Думайте об этом как о скользящем среднем, но в%.

Вывод из таблицы:

date         temp   monitor   trend        change_in_trend
12/4/2003    100    97.00      warming      false
12/5/2003    101    97.97      warming      false
12/8/2003    100    97.97      warming      false
12/9/2003    102    98.94      warming      false
12/10/2003   101    98.94      warming      false
12/11/2003   100    98.94      warming      false
12/12/2003    99    98.94      warming      false
12/15/2003    98    98.94      cooling      true
12/16/2003    97    98.94      cooling      false
12/17/2003    96    98.88      cooling      false
12/18/2003    95    97.85      cooling      false
12/19/2003    96    97.85      cooling      false
12/22/2003    97    97.85      cooling      false
12/23/2003    98    97.85      warming      true
12/24/2003    99    97.85      warming      false
12/26/2003   100    97.85      warming      false
12/29/2003   101    97.97      warming      false

Предположения:

percent_monitor = .03
warming_factor = 1 - percent_monitor
cooling_factor = 1 + percent_monitor

В моей таблице я установил столбцы в первой строке следующим образом:

monitor = temp * warming_factor
trending = warming
change_in_trend = false

Все остальные строки получены на основе значений столбцов текущей и предыдущей строк.

логика столбца монитора:

if temp > prev_monitor:
    if temp > prev_temp:
        if temp * warming_factor > prev_monitor:
            monitor = temp*warming_factor
        else:
            monitor = prev_monitor
    else:
        monitor = prev_monitor
else:
    if temp < prev_monitor:
        if temp * cooling_factor < prev_monitor:
            monitor = temp * cooling_factor
        else:
            monitor = prev_monitor
    else:
        monitor = prev_monitor

Логика трендовых столбцов:

if temp > prev_monitor:
    trending = warming
else:
    trending = cooling

изменение в логике столбца тренда:

if current_trend - previous_trend:
    change_in_trend = false
else:
    change in trend = true

Мне удалось перебрать кадр данных и применить логику без проблем. Однако на тысячах строк производительность ужасна.

Я пытался сделать это более похожим на 'панд' способом, но потерпел неудачу в каждой попытке.

Не смущая себя, вставляя мои попытки кода, есть ли кто-нибудь, кто мог бы предложить мне некоторую помощь?

Заранее спасибо!

1 Ответ

0 голосов
/ 08 сентября 2018

Поскольку вы хотите просто перенести это на Python и не настраивать Pandas, в частности, я выбрал подход, не связанный с Pandas. Я использовал ваши примеры строк и сделал 47124 строк за 0.182 секунд.

Pandas действительно хорош и интуитивно понятен для некоторых случаев использования, но может быть очень медленным для итерации. Эта страница объясняет некоторые из медленных применений Панд, одним из которых является в основном итерация индекса. Одним из способов сделать это было бы использование 5. Vectorization with NumPy arrays, но ваш вариант использования выглядит достаточно простым, чтобы это могло быть излишним и не стоило бы этого (учитывая, что вас зовут PythonNoob).

Ради ясности и скорости простое использование более простых функций Python может дать вам желаемую скорость.

Сначала я установил константы

percent_monitor = .03
warming_factor = 1 - percent_monitor
cooling_factor = 1 + percent_monitor

Затем (для простоты использования есть более чистые способы сделать это, но это очень ясно) Я задаю имена столбцов, соответствующие значениям столбцов:

DATE = 0
TEMP = 1
MONITOR = 2
TRENDING = 3
CHANGE_IN_TREND = 4

Затем я вытащил код вашего монитора в его собственную функцию (и немного почистил if -выступления:

def calculate_monitor(prev_monitor, current_temp, prev_temp):
     if (current_temp > prev_monitor) and (current_temp > prev_temp) and (current_temp * warming_factor) > prev_monitor:
            return current_temp * warming_factor
        elif (current_temp < prev_monitor) and ((current_temp * cooling_factor) < prev_monitor):
            return current_temp * cooling_factor
        else:
            return prev_monitor

Наконец, я прочитал код и обработал его:

data = [] # I am going to append everything to this
with open('weather_data.csv') as csv_file:
    previous_row = None
    csv_reader = csv.reader(csv_file, delimiter=' ')
    line_count = 0
    for row in csv_reader:
        cleaned_row = list(filter(None, row))
        if line_count == 0:
            # first row is column -- I am leaving it blank you can do whatever you want with it
            line_count += 1
        elif line_count == 1: # this is the first line
            previous_row = cleaned_row + [float(cleaned_row[TEMP]) * warming_factor, "warming", False]
            data.append(previous_row)
            line_count += 1
        else:
            monitor = calculate_monitor(float(previous_row[MONITOR]), float(cleaned_row[TEMP]), float(previous_row[TEMP]))
            current_trend = 'warming' if float(cleaned_row[TEMP]) > float(previous_row[MONITOR]) else 'cooling'
            change_in_trend = False if current_trend != previous_row[CHANGE_IN_TREND] else True
            previous_row = cleaned_row + [monitor, current_trend, change_in_trend]
            data.append(previous_row)
            line_count += 1

Это даст вам необходимую скорость. Если вы хотите преобразовать это в кадр данных pandas в конце, вы можете сделать:

df = pd.DataFrame(data, columns=['date', 'temp', 'monitor', 'current_trend', 'change_in_trend'])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...