Итеративно читаемый (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)
но это, конечно, просто читает все за один раз (включая строки с именами полей) - было бы здорово, если бы я мог как-то вкладывать блоки, что позволяет мне легко получить к ним доступ через числовые индексы...
У вас есть идеи, как мне лучше всего это сделать?
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)
* который я считаю устаревшим.
Я сделал это итеративно. очень итеративно. Ничто другое, кажется, не работает.
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
У меня не совсем получилось, но я думаю, это из-за того, как я копировал / вставлял данные. Попробуйте, дайте мне знать, если это не сработает.
Используя вдохновение из этого вопроса
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 от pandas, чтобы объединить их в один 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