2016-07-09 1 views
0

Это мой первый раз, когда я использовал Python (раньше я использовал R), поэтому, пожалуйста, несите меня по этому вопросу. В принципе, я хотел бы использовать цикл for для сравнения значения datetime в каждой строке со всеми остальными значениями datetime в других строках в кадре данных pandas pd, а если разница во времени составляет 4 часа или менее, сохраните эти строки в подмножестве объект df для последующей обработки. Однако я не уверен, с чего начать.Pandas Use Loop для сравнения datetime в каждой строке со всеми строками и сохранением подмножества результатов

Давайте предположим, что это мой набор данных:

   Origin   Destination    Time 
0   New York     Cairo 2016-03-28 02:00:00 
1   New York   Los Angeles 2016-03-28 04:00:00 
2    Boston    Hawaii 2016-03-28 06:00:00 
3   New York    Boston 2016-03-28 08:00:00 
4  Los Angeles    Boston 2016-03-28 10:00:00 
5  Los Angeles    Hawaii 2016-03-28 12:00:00 

Это то, что результат должен выглядеть следующим образом:

>>>df[0] 
       Origin   Destination    Time 
0   New York     Cairo 2016-03-28 02:00:00 
>>>df[1] 
       Origin   Destination    Time 
0   New York     Cairo 2016-03-28 02:00:00 
1   New York   Los Angeles 2016-03-28 04:00:00 
>>>df[2] 
       Origin   Destination    Time 
0   New York     Cairo 2016-03-28 02:00:00 
1   New York   Los Angeles 2016-03-28 04:00:00 
2    Boston    Hawaii 2016-03-28 06:00:00 
>>>df[3] 
1   New York   Los Angeles 2016-03-28 04:00:00 
2    Boston    Hawaii 2016-03-28 06:00:00 
3   New York    Boston 2016-03-28 08:00:00 
>>>df[5] 
       Origin   Destination    Time 
3   New York    Boston 2016-03-28 08:00:00 
4  Los Angeles    Boston 2016-03-28 10:00:00 
5  Los Angeles    Hawaii 2016-03-28 12:00:00 

Я не понимаю, как получить это.

+0

* 4 часа или менее хранить эти строки * ... четыре часа меньше по сравнению с какой конкретной метрикой ? Любая строка? Вы можете не подмножать ничего! – Parfait

ответ

3

Если вы хотите чистый панд решение без каких-либо петель, вы можете сделать это следующим образом:

  1. ли перекрестное соединение данных с самой
  2. выбора строк, где разница между временами составляет < 4 часа
  3. сгруппировать данные

Вот пример:

# Load file 
data = pd.read_csv("abc.csv", delimiter="\t") 
data["Time"] = pd.to_datetime(data["Time"], infer_datetime_format=True) 
data["Ignore"] = 1 
data = data.reset_index() 

# cross-join 
merged = pd.merge(data, data, how="outer", on="Ignore") 

# this is the magic 
merged = merged[(merged["Time_x"] - merged["Time_y"]).abs() < pd.Timedelta("4 hours")] 

# so you have some structure 
groups = merged.groupby("index_x").apply(lambda x : x.set_index("index_y")[["Origin_y", "Destination_y", "Time_y"]]) 

Это дает вам результат:

 Origin_y Destination_y Time_y 
index_x index_y   
0 0 New York Cairo 2016-03-28 02:00:00 
    1 New York Los Angeles 2016-03-28 04:00:00 
1 0 New York Cairo 2016-03-28 02:00:00 
    1 New York Los Angeles 2016-03-28 04:00:00 
    2 Boston Hawaii 2016-03-28 06:00:00 
2 1 New York Los Angeles 2016-03-28 04:00:00 
    2 Boston Hawaii 2016-03-28 06:00:00 
    3 New York Boston 2016-03-28 08:00:00 
3 2 Boston Hawaii 2016-03-28 06:00:00 
    3 New York Boston 2016-03-28 08:00:00 
... 

И вы можете получить доступ к отдельным строкам, как это:

> groups.T[0].T 

Origin_y Destination_y Time_y 
index_y   
0 New York Cairo 2016-03-28 02:00:00 
1 New York Los Angeles 2016-03-28 04:00:00 
+0

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

+0

Существует только одно подмножество для каждой исходной строки. Подмножество k'th содержит всю запись, которая находится в пределах 4 часов от k'th записи. –

1

Логика для петли:

df = [] 
for i, row in enumerate(rows): 
    df.append([row]) 
    try: 
     for next_row in rows[i + 1:]: 
      if abs(row['Time'] - next_row['Time']) < timedelta(hours=4): 
       df[i].append(next_row) 
      else: 
       break 
    except IndexError: 
     continue 
2

Начиная с этим :

   Origin    Destination     Time 
0    New York     Cairo 2016-03-28 00:00:00 
1    New York    Los Angeles 2016-03-28 02:00:00 
2    Boston     Hawaii 2016-03-28 04:00:00 
3    New York     Boston 2016-03-28 06:00:00 
4   Los Angeles     Boston 2016-03-28 08:00:00 
5   Los Angeles     Hawaii 2016-03-28 10:00:00 

Используйте dict для хранения ваших DataFrames, а затем получите доступ к Dict с индексом dataFrame.

NewDict = {} 
for i, e in df.iterrows(): 
    NewDict[i] = df[ (df['Time'] > e['Time']-pd.Timedelta('4 hours')) & (df['Time'] < e['Time'] + pd.Timedelta('4 hours'))] 

NewDict[0] 

       Origin    Destination     Time 
0    New York     Cairo 2016-03-28 00:00:00 
1    New York    Los Angeles 2016-03-28 02:00:00 

NewDict[4] 
       Origin    Destination     Time 
3    New York     Boston 2016-03-28 06:00:00 
4   Los Angeles     Boston 2016-03-28 08:00:00 
5   Los Angeles     Hawaii 2016-03-28 10:00:00 

Чтобы получить отсчеты:

for k, v in NewDict.iteritems(): 
    print "Key" ,k,"has" , len(v), "items" 

Key 0 has 2 items 
Key 1 has 3 items 
Key 2 has 3 items 
Key 3 has 3 items 
Key 4 has 3 items 
Key 5 has 2 items 

EDIT для петли в обратном направлении:

reverse = df.reindex(index=df.index[::-1]) 
revSorted = {} 
for i, e in reverse.iterrows(): 
    revSorted[i] = reverse[ (reverse['Time'] > e['Time']-pd.Timedelta('4 hours')) & (reverse['Time'] < e['Time'] + pd.Timedelta('4 hours'))] 
+0

Спасибо за быстрый ответ! Мне было интересно, можно ли повторить итерацию? То есть, начиная с нижнего ряда и заканчивая первой строкой. –

+0

Вам нужно будет отсортировать df.sort_values ​​(["Time" '], ascending = [False]) перед использованием iterrows. – Merlin

+0

Итак, этот код позволяет мне перебирать строки данных в обратном порядке? 'обратный = pd.reindex (индекс = pd.index [:: - 1])' 'revSorted = {}' 'для г, е в reverse.iterrows(): revSorted [ i] = reverse [(reverse ['Time']> e ['Time'] - pd.Timedelta ('60 секунд ')) & (reverse [' Time ']

Смежные вопросы