итеративно читать (tsv) файл для Pandas DataFrame

У меня есть некоторые экспериментальные данные, которые выглядят так: http://paste2.org/YzJL4e1b (слишком длинные, чтобы публиковать здесь ). Блоки, разделенные строками с именами полей, представляют собой разные испытания одного и того же эксперимента. Я хотел бы прочитать все в фрейме данных pandas, но объединить определенные испытания (например, 0,1,6,7 вместе взятые - и 2, 3,4,5 вместе взятые в другой группе). Это связано с тем, что разные испытания имеют немного разные условия, и я хотел бы проанализировать разницу результатов между этими условиями. У меня есть список чисел для разных условий из другого файла.

В настоящее время я делаю это:

tracker_data = pd.DataFrame
tracker_data = tracker_data.from_csv(bhpath+i+'_wmet.tsv', sep='\t', header=4)
tracker_data['GazePointXLeft'] = tracker_data['GazePointXLeft'].astype(np.float64) 

но это, конечно, просто читает все за один раз (включая строки имени поля) - было бы здорово, если бы я мог каким-то образом вкладывать блоки, что позволяет мне легко получать к ним доступ через числовые индексы...

У вас есть идеи, как мне лучше всего это сделать?


person TheChymera    schedule 20.06.2013    source источник
comment
Ах, я действительно близко, я думаю. @TheCymera, данные, которые вы загрузили, точно такие же, как на вашем компьютере? Как обрабатываются последние несколько столбцов в первой строке, где отсутствуют данные? Это просто вкладки?   -  person TomAugspurger    schedule 20.06.2013
comment
да, я взял содержимое с помощью копирования/вставки из leafpad (мой текстовый базовый редактор). Однако последние столбцы меня не особо беспокоят — это выборочное объединение, которое я хочу сделать.   -  person TheChymera    schedule 21.06.2013


Ответы (3)


Вы должны использовать read_csv вместо from_csv *:

tracker_data = pd.read_csv(bhpath+i+'_wmet.tsv', sep='\t', header=4)

Если вы хотите присоединиться к списку таких фреймов данных, вы можете использовать concat:

trackers = (pd.read_csv(bhpath+i+'_wmet.tsv', sep='\t', header=4) for i in range(?))
df = pd.concat(trackers)

* который, по моему мнению, устарел.

person Andy Hayden    schedule 20.06.2013
comment
Я думаю, вы неправильно поняли, что я хочу сделать - все эти блоки находятся в одном файле, а не в разных файлах, как предполагает наш код. - person TheChymera; 20.06.2013
comment
@TheChymera извиняюсь, я неправильно понял. Я не совсем уверен, что вам нужно. Вы запрашиваете чтение csv, которое читается только в определенных столбцах? - person Andy Hayden; 21.06.2013
comment
нет, я прошу способ прочитать весь файл .tsv (без разделяющих строк, содержащих строки), но таким образом, чтобы я мог вызывать блоки, разделенные этими строками, через индексы. Может быть, что-то вроде 3d-dataframe? - person TheChymera; 21.06.2013
comment
@TheChymera, вы ищете MultiIndex ... завтра конкретизирует ответ :) - person Andy Hayden; 21.06.2013

У меня не совсем получилось, но я думаю, что это из-за того, как я копировал/вставлял данные. Попробуйте это, дайте мне знать, если это не сработает.

Вдохновленный этим вопросом

pat = "TimeStamp\tGazePointXLeft\tGazePointYLeft\tValidityLeft\tGazePointXRight\tGazePointYRight\tValidityRight\tGazePointX\tGazePointY\tEvent\n"
with open('rec.txt') as infile:
    header, names, tail = infile.read().partition(pat)

names = names.split()  # get rid of the tabs here
all_data = tail.split(pat)
res = [pd.read_csv(StringIO(x), sep='\t', names=names) for x in all_data]

Мы читаем весь файл, поэтому это не сработает для больших файлов, а затем разбиваем его на основе известной строки, содержащей имена столбцов. tail — это просто строка с остальными данными, поэтому мы можем разделить ее, опять же, на основе имен. Может быть лучший способ, чем использование StringIO, но это должно работать.

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

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

Отдельный вопрос, как работать с несколькими блоками. Предполагая, что у вас есть список Dataframe, который я назвал res, вы можете использовать панды concat, чтобы объединить их вместе в один DataFrame с MultiIndex (также см. ссылку, опубликованную Энди).

In [122]: df = pd.concat(res, axis=1, keys=['a', 'b', 'c'])  # Use whatever makes sense for the keys

In [123]: df.xs('TimeStamp', level=1, axis=1)
Out[123]: 
     a    b    c
0  NaN  NaN  NaN
1  0.0  0.0  0.0
2  3.3  3.3  3.3
3  6.6  6.6  6.6
person TomAugspurger    schedule 20.06.2013
comment
Я попытался использовать код, но третья строка, похоже, не работает - заголовок, имена, хвост = infile.read().partition(pat) записывает все данные в заголовок, а имена и хвост пусты. - person TheChymera; 21.06.2013
comment
Поиграйте с Пэт. Чтобы убедиться, что вы получите именно то, что вам нужно, попробуйте f = open('rec.txt') и pat = f.read() 4 или 5 раз. f.read() будет читать по одной строке за раз, поэтому вам придется избавиться от заголовка. Как только вы назначите pat правильной строке, попробуйте еще раз. - person TomAugspurger; 21.06.2013

В итоге я сделал это итеративно. очень очень итеративно. Больше ничего не работает.

pat = 'TimeStamp    GazePointXLeft  GazePointYLeft  ValidityLeft    GazePointXRight GazePointYRight ValidityRight   GazePointX  GazePointY  Event'
with open(bhpath+fileid+'_wmet.tsv') as infile:
    eye_data = infile.read().split(pat)
    eye_data = [trial.split('\r\n') for trial in eye_data] # split at '\r'
    for idx, trial in enumerate(eye_data):
        trial = [row.split('\t') for row in trial]
        eye_data[idx] = trial
person TheChymera    schedule 10.07.2013