Фильтрация pandas dataframe по дате для подсчета просмотров для временной шкалы программ - PullRequest
0 голосов
/ 30 мая 2019

Мне нужно посчитать количество зрителей по программе для потокового канала из файла журнала json.Я идентифицирую программы по времени их запуска, например:

До сих пор у меня есть два таких кадра данных:

Первый содержит все метки времени из файла журнала

viewers_from_log = pd.read_json('sqllog.json', encoding='UTF-8')
# Convert date string to pandas datetime object:
viewers_from_log['time'] = pd.to_datetime(viewers_from_log['time'])

enter image description here

Исходный файл JSON:

[
    {
        "logid": 191605,
        "time": "0:00:17"
    },
    {
        "logid": 191607,
        "time": "0:00:26"
    },
    {
        "logid": 191611,
        "time": "0:01:20"
    }
]

Второй содержит время начала и названия программ

programs_start_time = pd.DataFrame.from_dict('programs.json', orient='index')

enter image description here Исходный файл JSON:

{
    "2019-05-29": [
        {
            "title": "\"Amiről a kövek mesélnek\"",
            "startTime_dt": "2019-05-29T00:00:40Z"
        },
        {
            "title": "Koffer - Kedvcsináló Kul(t)túrák Külföldön",
            "startTime_dt": "2019-05-29T00:22:44Z"
        },
        {
            "title": "Gubancok",
            "startTime_dt": "2019-05-29T00:48:08Z"
        }
    ]
}

Итак, мне нужно подсчитать записи / программу в файле журнала и связать их с названиями программ.

Ответы [ 3 ]

2 голосов
/ 30 мая 2019

Мой подход состоит в том, чтобы вырезать данные журнала для каждого диапазона дат из данных программы и получить форму. Затем добавьте столбец для данных программы с результатами:

import pandas as pd

# setup test data
log_data = {'Time': ['2019-05-30 00:00:26', '2019-05-30 00:00:50', '2019-05-30 00:05:50','2019-05-30 00:23:26']}
log_data = pd.DataFrame(data=log_data)

program_data = {'Time': ['2019-05-30 00:00:00', '2019-05-30 00:22:44'],
            'Program': ['Program 1', 'Program 2']}
program_data = pd.DataFrame(data=program_data)


counts = []
for index, row in program_data.iterrows():
    # get counts on selected range
    try:
        log_range = log_data[(log_data['Time'] > program_data.loc[index].values[0]) & (log_data['Time'] < program_data.loc[index+1].values[0])]
        counts.append(log_range.shape[0])
    except:
        log_range = log_data[log_data['Time'] > program_data.loc[index].values[0]]
        counts.append(log_range.shape[0])

 # add aditional column with collected counts
 program_data['Counts'] = counts

Выход:

                  Time    Program  Counts
 0  2019-05-30 00:00:00  Program 1       3
 1  2019-05-30 00:22:44  Program 2       1
1 голос
/ 30 мая 2019

Решение с гистограммой, используя numpy:

import pandas as pd
import numpy as np

df_p = pd.DataFrame([
        {
            "title": "\"Amiről a kövek mesélnek\"",
            "startTime_dt": "2019-05-29T00:00:40Z"
        },
        {
            "title": "Koffer - Kedvcsináló Kul(t)túrák Külföldön",
            "startTime_dt": "2019-05-29T00:22:44Z"
        },
        {
            "title": "Gubancok",
            "startTime_dt": "2019-05-29T00:48:08Z"
        }
    ])

df_v = pd.DataFrame([
    {
        "logid": 191605,
        "time": "2019-05-29 0:00:17"
    },
    {
        "logid": 191607,
        "time": "2019-05-29 0:00:26"
    },
    {
        "logid": 191611,
        "time": "2019-05-29 0:01:20"
    }
])

df_p.startTime_dt = pd.to_datetime(df_p.startTime_dt)
df_v.time = pd.to_datetime(df_v.time)

# here's part where I convert datetime to timestamp in seconds - astype(int) casts it to nanoseconds, hence there's // 10**9
programmes_start = df_p.startTime_dt.astype(int).values // 10**9
viewings_starts = df_v.time.astype(int).values // 10**9

# make bins for histogram
# add zero to the beginning of the array
# add value that is time an hour after the start of the last given programme to the end of the array
programmes_start = np.pad(programmes_start, (1, 1), mode='constant', constant_values=(0, programmes_start.max()+3600))

histogram = np.histogram(viewings_starts, bins=programmes_start)
print(histogram[0]
# prints [2 1 0 0]

Интерпретация: было 2 записи в журнале до начала «Amir Aml a kövek mesélnek», 1 запись в журнале между запусками «Amiről a kövek mesélnek» и «Koffer - Kedvcsináló Kul (t) túrák Külföldön», 0 записей в журнале между запусками «Koffer - Kedvcsináló Kul (t) túrák Külföldön» и «Gubancok» и 0 записей после начала «Gubancok». Что, глядя на предоставленные вами данные, кажется правильным :) Надеюсь, это поможет.

ПРИМЕЧАНИЕ: я предполагаю, что у вас есть дата просмотров. У вас их нет в файле журнала примера, но они появляются на скриншоте - так что я предположил, что вы можете как-то вычислить / получить их, и добавил их вручную в dict ввода.

1 голос
/ 30 мая 2019

Рабочий (но, возможно, немного быстрый и грязный) метод:

Используйте метод .shift(-1) в столбце отметок времени programs_start_time кадра данных, чтобы получить дополнительный столбец с именем date_end, указывающим отметку времени окончания для каждой телевизионной программы.

Затем для каждого example_timestamp в файле журнала вы можете запросить информационный кадр телевизионных программ следующим образом: df[(df['date_start']=<example_timestamp) & (df['date_end']>example_timestamp)] (убедитесь, что вы заменили df именем вашего информационного кадра: programs_start_time), что даст вам ровно одну строку информационного кадра и извлеките из него название телевизионной программы.

Надеюсь, это поможет!

...