#python #pandas #csv
#python #панды #csv
Вопрос:
У меня есть несколько разных файлов csv с разным количеством заголовков. Мне нужно прочитать эти csv без использования каких-либо модулей, поэтому я предпринял попытку. Как мне распечатать столбцы разных CSV, а затем получить среднее, минимальное, максимальное и стандартное отклонение для каждого из них, а также сопоставить их друг с другом?
Вот что у меня есть до сих пор, но в этом случае списки были жестко запрограммированы. В этом случае файл, который я в него читаю, имеет 2 заголовка для даты, времени и показаний барометра, но я также буду читать другие файлы, в которых намного больше заголовков и больше информации.
Я могу использовать pandas, как только я записал csv в фрейм данных python, поэтому я его импортировал. Любые рекомендации или идеи приветствуются. Спасибо!
import pandas as pd
def readmyfile(InputFile):
list_date = []
list_baro = []
with open(InputFile, 'r') as file:
for line in file:
row = line.split(',')
list_date.append(row[0].strip('"'))
list_baro.append(row[1].strip('n'))
# df = pd.DataFrame(list_date[1:])
# df2 = pd.DataFrame(list_baro[1:])
# average = np.mean(df2)
print(list_date)
print(list_baro)
readmyfile('barometer-last-year.csv')
Некоторые данные, которые есть в barometer-last-year.csv:
"DateTime","Baro"
"2016-10-09 00:00:00",1021.9
"2016-10-10 00:00:00",1019.9
"2016-10-11 00:00:00",1015.8
"2016-10-12 00:00:00",1013.2
"2016-10-13 00:00:00",1005.9
"2016-10-14 00:00:00",998.6
"2016-10-15 00:00:00",998
"2016-10-16 00:00:00",1002.2
"2016-10-17 00:00:00",1009.8
"2016-10-18 00:00:00",1013.4
"2016-10-19 00:00:00",1015.8
"2016-10-20 00:00:00",1015.7
и вот некоторые данные, которые у меня есть в других CSV:
"DateTime","Temperature","Temperature_range (low)","Temperature_range (high)"
"2016-10-09 00:00:00",10.66,7.2,13.8
"2016-10-10 00:00:00",8.94,5.6,12.8
"2016-10-11 00:00:00",8.69,5.3,14.3
"2016-10-12 00:00:00",11.55,9,14.9
"2016-10-13 00:00:00",9.4,6,13.3
"2016-10-14 00:00:00",9.85,6.8,13.3
"2016-10-15 00:00:00",10.72,8.2,14.7
"2016-10-16 00:00:00",11.28,7.8,14.5
"2016-10-17 00:00:00",11.84,10,15
"2016-10-18 00:00:00",10.24,8.2,12.7
"2016-10-19 00:00:00",10.2,8,13.4
"2016-10-20 00:00:00",9.76,7.2,12.8
"2016-10-21 00:00:00",7.96,3.7,15.1
"2016-10-22 00:00:00",7.9,5.3,13
Комментарии:
1. Можете ли вы предоставить некоторые примеры данных из файлов csv, чтобы структура данных была очевидной?
2. Конечно, позвольте мне отредактировать его.
3. Каким должен быть результат функции, считывающей эти файлы .csv? Что вы планируете с ними делать? Если вы читаете файл csv, у вас уже есть данные в списке, поэтому я хочу знать, нужно ли вам преобразовать данные или достаточно простой загрузки.
4. Я хочу иметь возможность выводить максимальное и минимальное значение volumns (кроме даты и времени) вместе со средним и средним значением каждого из них. Тогда в идеале нарисуйте их, чтобы у меня было что-то визуальное для их сравнения.
5. Вы хотите загрузить разные CSV-файлы, а затем отобразить их на временной шкале, чтобы показать изменение различных параметров во времени?
Ответ №1:
Я реализовал parse_csv()
функцию внутри следующего кода, который не использует модули. Он поддерживает любой разделитель (например ,
) между ячейками и любой символ, заключенный в кавычки (например "
), также он корректно обрабатывает разделители, расположенные внутри строк, заключенных в кавычки, например, строка CSV "a,b,c",d
будет обрабатываться как две ячейки a,b,c
и d
. Пустые строки в CSV пропускаются.
Первая строка обрабатывается как имена столбцов. Функция возвращает имена столбцов и остальные строки отдельно, так что эти два могут быть переданы непосредственно pd.DataFrame()
конструктору.
Функция принимает header
аргумент (имена столбцов), он должен быть True
, если строка заголовка должна считываться как первая строка файла CSV, он должен быть False
или содержать список имен столбцов, если в файле CSV нет строки заголовка.
Входной файл CSV может быть передан функции различными способами 1) Через file
аргумент, который может быть либо строкой, содержащей путь к файлу или имя, либо открытым для чтения объектом file. 2) text
Аргумент Through, который может быть либо строкой, содержащей текст CSV, либо байтами, содержащими содержимое файла CSV.
В простейшей форме вы просто делаете columns, table = parse_csv(file = 'test.csv')
.
def parse_csv(*, file = None, text = None, sep = ',', quote = '"', header = True, encoding = 'utf-8'):
assert file is not None or text is not None, f'Either text or file argument should be provided!'
if text is None:
if type(file) is str:
with open(file, 'r', encoding = encoding) as f:
text = f.read()
elif type(file) is bytes:
text = file
else:
text = file.read()
if type(text) is bytes:
text = text.decode(encoding)
first, ncols, table = True, None, []
for line in text.splitlines():
line = line.strip()
if not line:
continue
parts = line.split(sep)
i = 0
entries = []
while True:
if i >= len(parts):
break
if not parts[i].startswith(quote):
entries.append(parts[i])
i = 1
else:
entries.append(parts[i][len(quote):])
while True:
if parts[i].endswith(quote):
entries[-1] = entries[-1][:-len(quote)]
break
i = 1
entries[-1] = sep parts[i]
i = 1
if first:
if header is True:
hrow = True
header = entries
ncols = len(entries)
elif header is False:
hrow = False
header = None
ncols = len(entries)
else:
hrow = False
assert type(header) in [list, tuple], type(header)
header = list(header)
ncols = len(header)
first = False
else:
hrow = False
if not hrow:
assert len(entries) == ncols, f'Wrong number of columns (expected {ncols}) in row: {line}'
table.append(entries)
if first and type(header) is bool:
header = None
return header, table
import pandas as pd
# ----- First example -----
text = """
"DateTime","Temperature","Temperature_range (low)","Temperature_range (high)"
"2016-10-09 00:00:00",10.66,7.2,13.8
"2016-10-10 00:00:00",8.94,5.6,12.8
"2016-10-11 00:00:00",8.69,5.3,14.3
"2016-10-12 00:00:00",11.55,9,14.9
"2016-10-13 00:00:00",9.4,6,13.3
"2016-10-14 00:00:00",9.85,6.8,13.3
"2016-10-15 00:00:00",10.72,8.2,14.7
"2016-10-16 00:00:00",11.28,7.8,14.5
"2016-10-17 00:00:00",11.84,10,15
"2016-10-18 00:00:00",10.24,8.2,12.7
"2016-10-19 00:00:00",10.2,8,13.4
"2016-10-20 00:00:00",9.76,7.2,12.8
"2016-10-21 00:00:00",7.96,3.7,15.1
"2016-10-22 00:00:00",7.9,5.3,13
"""
columns, table = parse_csv(text = text)
df = pd.DataFrame(table, columns = columns)
print('-' * 30)
print(df)
# ----- Second example -----
text = """
a|b|'c|d'|e
1|2|3|4
"""
ref = None
for header in [
True, False, ['first', 'second', 'third', 'fourth'],
]:
columns, table = parse_csv(text = text, sep = '|', quote = "'", header = header)
df = pd.DataFrame(table, columns = columns)
print('-' * 30)
print(df)
if ref is None:
ref = (columns, table)
# ----- Third example -----
import io
with open('test.csv', 'w', encoding = 'utf-8') as f:
f.write(text)
for file in [
io.StringIO(text), io.BytesIO(text.encode('utf-8')), text.encode('utf-8'),
'test.csv', open('test.csv', 'r', encoding = 'utf-8'), open('test.csv', 'rb'),
]:
columns, table = parse_csv(file = file, sep = '|', quote = "'")
assert (columns, table) == ref
Вывод:
------------------------------
DateTime Temperature Temperature_range (low) Temperature_range (high)
0 2016-10-09 00:00:00 10.66 7.2 13.8
1 2016-10-10 00:00:00 8.94 5.6 12.8
2 2016-10-11 00:00:00 8.69 5.3 14.3
3 2016-10-12 00:00:00 11.55 9 14.9
4 2016-10-13 00:00:00 9.4 6 13.3
5 2016-10-14 00:00:00 9.85 6.8 13.3
6 2016-10-15 00:00:00 10.72 8.2 14.7
7 2016-10-16 00:00:00 11.28 7.8 14.5
8 2016-10-17 00:00:00 11.84 10 15
9 2016-10-18 00:00:00 10.24 8.2 12.7
10 2016-10-19 00:00:00 10.2 8 13.4
11 2016-10-20 00:00:00 9.76 7.2 12.8
12 2016-10-21 00:00:00 7.96 3.7 15.1
13 2016-10-22 00:00:00 7.9 5.3 13
------------------------------
a b c|d e
0 1 2 3 4
------------------------------
0 1 2 3
0 a b c|d e
1 1 2 3 4
------------------------------
first second third fourth
0 a b c|d e
1 1 2 3 4
Комментарии:
1. Ах, это имеет гораздо больше смысла. Что касается ввода текста, есть ли способ, которым я могу ввести CSV непосредственно в него без необходимости превращать его в текст? Спасибо!
2. В настоящее время функция @Nhyi имеет дело только с входной текстовой строкой. Вам просто нужно прочитать свой входной файл самостоятельно, просто сделайте:
with open('file_name.csv', 'r', encoding = 'utf-8') as f: columns, table = parse_csv(f.read())
. Или вы можете добавить эту логику чтения файлов в начало моей функции.3. Ах, я попробую и дам вам знать, что произойдет. Я собирался добавить его в начало функции, но не приведет ли это к тому, что splitlines() станет проблемой?
4. @Nhyi Теперь я изменю свою функцию, чтобы она могла поддерживать различные типы ввода (текст, файл и т. Д.).
5. Приветствую, очень признателен. Я определенно понимаю, как вы можете поместить его вне функции, просто объединив его с функцией parse_csv, с чем у меня сейчас возникают проблемы.