Как извлечь целевую строку, строку перед и строку после файла CSV?

Чтобы преобразовать строки типа 'volvo', 'bmw' в целые числа, сначала преобразуйте их в dataframe, затем передайте его pandas.get_dummies ()

  df  = DataFrame.from_csv("myFile.csv")
  df_transform = pd.get_dummies( df )
  print( df_transform )
1
задан Sailanarmo 13 July 2018 в 21:26
поделиться

3 ответа

Я использовал бы другой подход:

  • сохранит предыдущую строку в вашем цикле
  • , если соответствует, затем используйте next, чтобы получить следующую строку, и верните 3 строки

, как это (я добавил комментарий, поскольку timeInRow следует извлечь из row, но ваш код не показывает его):

prev_row = []  # just in case it matches at first row
for row in csvFile:
    # something must be done to extract timeInRow from row here!
    if timeID == timeInRow:
        return [prev_row,row,next(csvFile,[])]
    prev_row = row  # save current row for next iteration

next использует значение пустого списка по умолчанию только в том случае, если строка last соответствует (исключает исключение StopIteration)

Этот линейный подход работает, но если строки отсортированы по времени, и вам нужно выполнить несколько поисков, лучший подход (быстрее), вероятно, приведет к созданию списка строк, списка раз, затем используйте модуль bisect для вычисления точки вставки в списке раз, убедитесь, что совпадение времени и использование индекса для возврата фрагмента списка строк.

Что-то вроде:

list_of_rows = list(csvFile)
list_of_times = [x[3] for x in list_of_rows] # assume that the time is the 4th column here
i = bisect.bisect(list_of_rows,timeInRow)
if i < len(list_of_rows) and list_of_rows[i] == timeInRow:
    return list_of_rows[max(i-1,0):min(i+2,len(list_of_rows)]

Если вам нужно выполнить только 1 поиск, это происходит медленнее, вам все равно необходимо создать список O(n) + O(log(n)). Но если вы хотите выполнить несколько поисков времени в том же списке, стоимость будет O(log(n)) за поиск.

2
ответ дан Jean-François Fabre 17 August 2018 в 12:08
поделиться
  • 1
    timeInRow извлекается с помощью другой функции, которую я написал. Я попытался этот метод, и я получил сообщение об ошибке TypeError: list object is not an iterator. – Sailanarmo 13 July 2018 в 21:45
  • 2
    ooops зафиксировала мою next часть, которая должна применяться к объекту csvFile, а не row :) – Jean-François Fabre 13 July 2018 в 21:48
  • 3
    Извинения за то, что вы так поздно опоздали, как этот метод будет заходить за пределы CSV-файла? Если совпадение заканчивается тем, что первая или последняя вещь в файле будет нарушена? – Sailanarmo 16 July 2018 в 15:15
  • 4
    нет, это не так, потому что нарезка остановится в первую очередь. Ну, может быть, есть угловой случай, редактирование – Jean-François Fabre 16 July 2018 в 15:23
  • 5
    нет в первом методе, если он будет найден в начале, он вернет пустой список для предыдущего, и если он будет найден в конце, будет возвращен пустой список для следующего. – Jean-François Fabre 16 July 2018 в 15:29

Альтернативный (функциональный) подход к рассмотренным выше будет заключаться в использовании zip или его вариации. Что-то вроде:

rows = list(csv.reader(f))
for x, y, z in zip(rows, rows[1:], rows[2:]):
    # y is the middle row, x is above it, and z below it
    pass

Если вы хотите включить первые две и последние две строки в своей итерации в качестве

(None, None, rows[0])
(None, rows[0], rows[1])
(rows[-2], rows[-1], None)
(rows[-1], None, None)

, тогда вам придется предварительно и после отложить rows список двумя None на обоих концах.

Не сказать, что это обязательно лучше, чем другие ответы, но это альтернативный подход, который я хотел бы рассмотреть.

[Редактировать ]

Использование itertools.islice по предложению Jean-François:

rows = list(csv.reader(f))
from itertools import islice
for x, y, z in zip(rows, islice(rows, 1, None), islice(rows, 2, None)):
    # y is the middle row, x is above it, and z below it
    pass
1
ответ дан BowlingHawk95 17 August 2018 в 12:08
поделиться
  • 1
    в этом случае было бы лучше использовать itertools.islice, чтобы не создавать 2 копии списка rows. – Jean-François Fabre 13 July 2018 в 21:49
  • 2
    Что-то вроде приведенного выше @ Jean-FrançoisFabre? Я не использовал islice, но кажется разумным для этого варианта использования. – BowlingHawk95 13 July 2018 в 21:57

Для этого вы можете использовать deque .

Учитывая:

$ cat /tmp/file.csv
firstName,lastName,email,phoneNumber
John,Doe,john@doe.com,0123456789
Jane,Doe,jane@doe.com,9876543210
James,Bond,james.bond@mi6.co.uk,0612345678

Предположим, что вы хотите, чтобы линия с Jane и строка перед и после.

Попробуйте:

import csv 
from collections import deque 

dq=deque([[None] for _ in range(3)],maxlen=3)
with open(fn,'r') as f:
    for row in csv.reader(f):
        dq.append(row)
        if dq[-2][0]=='Jane': break # here you can use your custom function 

Затем:

 >>> dq
 deque([['John', 'Doe', 'john@doe.com', '0123456789'], ['Jane', 'Doe', 'jane@doe.com', '9876543210'], ['James', 'Bond', 'james.bond@mi6.co.uk', '0612345678']], maxlen=3)
1
ответ дан dawg 17 August 2018 в 12:08
поделиться
  • 1
    Будет ли dq.append(row) добавить все в deque и выбить все, как только достигнет максимальной длины 3? – Sailanarmo 13 July 2018 в 21:48
  • 2
    @Sailanarmo: Да. Независимо от значения maxlen=3, элементы добавляются на одном конце, а затем удаляются на другом конце, чтобы сохранить длину в maxlen. Он действует как скользящее окно в более длинный элемент данных. Вы также можете не иметь maxlen, и поэтому deque будет вести себя скорее как список (с некоторыми отличиями, в том числе сильными нажатиями и появлением на обоих концах) – dawg 13 July 2018 в 21:51
  • 3
    извинения за возвращение так поздно, будет ли этот метод за пределами? Что, если матч заканчивается тем, что является последним в CSV-файле или в первом? Разве это сломается? Или есть исключение, которое я могу поймать? Или я могу как-то заполнить эту запись нулевым? – Sailanarmo 16 July 2018 в 15:14
  • 4
    Если вы первый, вы получите [[None], [Line 1], [Line 2]] Если ваше совпадение является последней строкой, вы можете добавить else в цикл for и проверить это условие в конце цикла. Тогда deque будет последними тремя строками. – dawg 16 July 2018 в 15:19
Другие вопросы по тегам:

Похожие вопросы: