Страницы

Поиск по вопросам

Показаны сообщения с ярлыком csv. Показать все сообщения
Показаны сообщения с ярлыком csv. Показать все сообщения

суббота, 4 апреля 2020 г.

ValueError: dict contains fields not in fieldnames

#python #сортировка #csv

                    
with open('data.csv', "r") as csv_file:
    csv_reader = csv.DictReader(csv_file)

with open('gaze.csv', 'w') as new_file:
    fieldnames = ['gaze_0_x', 'gaze_0_y', 'gaze_0_z', 'gaze_1_x', 'gaze_1_y', 'gaze_2_z']

    csv_writer = csv.DictWriter(new_file, fieldnames=fieldnames, delimiter='\t')

    csv_writer.writeheader()

    for line in csv_reader:
        csv_writer.writerow(line)


ValueError: dict contains fields not in fieldnames: ' x_59', ' X_18', ' x_27', '
y_42', ' Y_16', ' pose_Rz', ' Y_32', ' Y_54', ' x_26', ' x_16', ' p_5', ' X_67', '
p_14', ' x_17', ' Z_2', '...И так далее 400 переменных, которые я не хочу задействовать. 
    


Ответы

Ответ 1



Так передайте fieldnames в DictReader, чтобы он лишних полей не читал.

пятница, 13 марта 2020 г.

Сохранение данных в CSV файл

#java #android #csv


после сохранения в файл при открытии с excel кодировка бывает не понятной(только
если текст на русском), а через notepad++ все читабельно, в чем проблема подскажите
пожалуйста

String filename = "mytest.csv";
String entry = "Задача" +";"+"первая";
try {
    FileOutputStream out = openFileOutput(filename, Context.MODE_APPEND);
    out.write(entry.getBytes());
    out.close();

} catch (Exception e) {
    e.printStackTrace();
}


и если не сложно подскажите что почитать для создания csv файла в android
    


Ответы

Ответ 1



Попробуйте или в файл сохранять в нужной кодировке: // Строка Unicode String string = "..."; // Записываем строку в текстовый файл в кодировке Cp866 PrintWriter pw = new PrintWriter // класс с методами записи строк (new OutputStreamWriter // класс-преобразователь (new FileOutputStream // класс записи байтов в файл ("file.txt"), "Cp866"); pw.println(string); // записываем строку в файл pw.close(); или, например, строку сразу записывать в нужной кодировке // Строка Unicode String string = "..."; // Записываем строку в текстовый файл в двух кодировках (Cp866 и Cp1251) OutputStream os = new FileOutputStream("file.txt"); // класс записи байтов в файл // Записываем строку в кодировке Cp866 os.write( string.getBytes("Cp866") ); // Записываем строку в кодировке Cp1251 os.write( string.getBytes("Cp1251") ); os.close(); Если файл у вас уже существует, можно сделать проверку в самом начале и удалить его: File f = new File("1.txt"); if (f.exists()) f.delete();

воскресенье, 1 марта 2020 г.

почему появляется столбец 'Unnamed'

#python #pandas #dataframe #csv


я создал датафрейм , в нём 3 колнки. Перегоняю его в файл. Читаю данные с файла и
вижу новый столбец 'Unnamed' . Всё бы ничего , но я не могу его удалить , вылетает ошибка:

ValueError: labels ['Unnamed'] not contained in axis


откуда вообще он взялся и что с ним делать ?
    


Ответы

Ответ 1



Скорее всего вы сохранили CSV файл с индексом (по умполчанию). Как это проверить: In [31]: df.columns.tolist() Out[31]: ['Unnamed: 0', 'a', 'b', 'c'] Пример: In [16]: df = pd.DataFrame(np.arange(1,10).reshape(3,3), columns=list('abc')) In [17]: df Out[17]: a b c 0 1 2 3 1 4 5 6 2 7 8 9 In [18]: df.to_csv(r'c:/temp/test.csv') теперь если просто прочитать его, то получим столбец Unnamed: 0 (т.к. индекс был безымянным): In [20]: x = pd.read_csv(r'c:/temp/test.csv') In [21]: x Out[21]: Unnamed: 0 a b c 0 0 1 2 3 1 1 4 5 6 2 2 7 8 9 вот как это выглядит в CSV файле: In [22]: print(Path(r'c:/temp/test.csv').read_text()) ,a,b,c 0,1,2,3 1,4,5,6 2,7,8,9 Как это обойти: In [23]: x = pd.read_csv(r'c:/temp/test.csv', index_col=0) In [24]: x Out[24]: a b c 0 1 2 3 1 4 5 6 2 7 8 9 или сохранять DataFrame без индекса: In [25]: df.to_csv(r'c:/temp/test.csv', index=False) In [26]: print(Path(r'c:/temp/test.csv').read_text()) a,b,c 1,2,3 4,5,6 7,8,9 In [27]: pd.read_csv(r'c:/temp/test.csv') Out[27]: a b c 0 1 2 3 1 4 5 6 2 7 8 9

пятница, 28 февраля 2020 г.

Связать два CSV файла по столбцу (с агрегацией)

#python #csv


Суть данного скрипта в том, чтобы он вывел список значений из 2 файла, соответствующих
значению id из первого файла. В итоге он выводит список лишь для самого первого id,
а для остальных выдает пустой список "[ ]". Причем для каждого из этих id есть соответствующие
значения, пустых списков там выводиться не должно. Что я не так делаю?

posts_table = open("posts.csv")
cat_rel_table = open("category_relationship.csv")

reader_1 = csv.DictReader(posts_table)
reader_2 = csv.DictReader(cat_rel_table)

def cat_name(post_id):
    cat_list = []
    for cat in reader_2:
        if cat['post_id'] == post_id:
            cat_list.append(cat['cat_id'])
    return cat_list

for post in reader_1:
    if (post['type'] == "8" and post['status'] == "1"):
        print(post['id'], cat_name(post['id']))


вот пример содержимого posts.csv:

"id","type","price","new_price","from_date","to_date","parent","created_at","author","featured","template","stock","view","status","barcode"
"84","8","117","0","0000-00-00 00:00:00","0000-00-00 00:00:00","0","2017-10-12 14:37:38","1","../uploads/posts/2017/10/1-10-r-c-audi-r8-v10-compl-6v.jpg","0","10","0","2",
"85","8","28","0","0000-00-00 00:00:00","0000-00-00 00:00:00","266","2017-10-12 17:41:45","1","../uploads/posts/2017/10/0011543346227-a.jpg","0","10","0","2",
"86","8","13","0","0000-00-00 00:00:00","0000-00-00 00:00:00","266","2017-10-19 10:38:06","1","../uploads/posts/2017/10/81XHlhvCsJL._SL1500_.jpg","0","10","0","2",
"87","8","28","0","0000-00-00 00:00:00","0000-00-00 00:00:00","266","2017-10-19 11:03:55","4","../uploads/posts/2017/10/cat-9-inch-big-builder-l&s-shaking-machine-vehicle-dump-truck--5AE442DA.zoom.jpg","0","10","0","1","11543346210"
"88","8","28","0","0000-00-00 00:00:00","0000-00-00 00:00:00","0","2017-10-19 11:05:59","1","../uploads/posts/2017/10/pTRUCA1-22577036_alternate1_enh-z6.jpg","0","10","0","2",


Пример category_relationship.csv

"id","type","cat_id","post_id","status"
"31","8","21","84","2"
"32","8","21","85","2"
"33","8","20","86","2"
"34","8","21","86","2"
"35","8","20","87","1"
"36","8","21","87","2"
"37","8","20","88","2"
"38","8","21","88","2"


Ожидаемый вывод: {131: ['2', '11', '43', '45', '72', '5', '8', '44']} (для каждого
айдишника). Т.е. слева айдишник из первой таблицы, а справа список значений который
скрипт получает из другой таблицы.
    


Ответы

Ответ 1



Вот теперь разобрался. У Вас, проблема в том, что конструкции open("category_relationship.csv") и csv.DictReader выдают объекты типа итератора, и после первого прохода курсор остается в конце, соответственно значений он более не возвращает, отсюда и пустой вывод при каждом следующем проходе. Для того, чтобы этого избежать, нужно считывать данные из файла для каждого прохода. Получается вот так: import csv posts = csv.DictReader(open("posts.csv")) def cat_list(post_id): return [item['cat_id'] for item in csv.DictReader(open("category_relationship.csv")) if item['post_id'] == post_id] di = {post['id']: cat_list(post['id']) for post in posts if post['type'] == "8" and post['status'] == "1"} # теперь словарь di можно использовать по своему усмотрению print(di) for key, val in di.items(): print(key, val) Решение на основе предложения топикстртера: import csv cat_file = open("category_relationship.csv") category = csv.DictReader(cat_file) posts = csv.DictReader(open("posts.csv")) # Поскольку здесь только один проход, скомбинируем. def cat_list(post_id): cat_file.seek(0) # Возвращаем курсор в начальное положение. return [item['cat_id'] for item in category if item['post_id'] == post_id] di = {post['id']: cat_list(post['id']) for post in posts if post['type'] == "8" and post['status'] == "1"} # теперь словарь можно использовать по своему усмотрению print(di) for key, val in di.items(): print(key, val)

Ответ 2



Для подобных задач идеально подходит модуль Pandas: import pandas as pd # pip install pandas p = pd.read_csv(r'D:\temp\posts.csv') c = pd.read_csv(r'D:\temp\category_relationship.csv') res = (p.loc[(p['type']==8) & (p['status']==1), ['id']] .set_index('id') .join(c.groupby('post_id')['cat_id'] .apply(lambda x: x.values.tolist()))) результат: In [372]: p Out[372]: id type price new_price from_date ... template stock view status barcode 0 84 8 117 0 0000-00-00 00:00:00 ... 0 10 0 2 NaN 1 85 8 28 0 0000-00-00 00:00:00 ... 0 10 0 1 NaN 2 86 8 13 0 0000-00-00 00:00:00 ... 0 10 0 2 NaN 3 87 8 28 0 0000-00-00 00:00:00 ... 0 10 0 1 1.154335e+10 4 88 8 28 0 0000-00-00 00:00:00 ... 0 10 0 2 NaN [5 rows x 15 columns] In [373]: c Out[373]: id type cat_id post_id status 0 31 8 21 84 2 1 32 8 21 85 2 2 33 8 20 86 2 3 34 8 21 86 2 4 35 8 20 87 1 5 36 8 21 87 2 6 37 8 20 88 2 7 38 8 21 88 2 In [374]: res Out[374]: cat_id id 85 [21] 87 [20, 21] In [375]: res.to_dict()['cat_id'] Out[375]: {85: [21], 87: [20, 21]}

среда, 26 февраля 2020 г.

Как конвертировать JSON/XML в CSV/XLS?

#python #json #xml #csv


Есть файл JSON (попутно конвертировал в XML) размером 60МБ, где каждая строка имеет
по два значения:

{"item1": "default", "item2":"1473"}


или же то же самое в XML:

Название1473


Как можно с помощью Python правильно конвертировать их в CSV/XLS?

P.S. В item1 часто попадаются запятые.
    


Ответы

Ответ 1



Пример входного JSON: [ {"item1": "default", "item2":"1473"}, {"item1": "a,b,c", "item2":"4567"} ] Конвертация JSON --> CSV: import pandas as pd # pip install pandas pd.read_json(r"C:\temp\test.json").to_csv(r"c:\temp\result.csv", index=False) Результат: item1,item2 default,1473 "a,b,c",4567 Конвертация JSON --> Excel: import pandas as pd # pip install pandas pd.read_json(r"C:\temp\test.json").to_excel(r"c:\temp\result.xlsx", index=False)

вторник, 18 февраля 2020 г.

Сохранение JSON ответа в сsv. Python

#python #json #python_3x #парсер #csv


В общем сохраняю json ответ в сsv, получается как на картинке.



В итоге хочу достигнуть такой результат. Подскажите как реализовать(желательно с
примером), или литературу какую-нибудь.



Вот сам код.

# -*- coding: utf-8 -*-

import requests
from bs4 import BeautifulSoup
from random import choice
from time import sleep
from random import uniform
import json
import csv

def get_html(url,useragent,proxy,StartFroms):
    #print("get_html")
    #print(StartFroms)
    #print(proxy)
    #print(useragent)
    s = requests.Session()
    s.get("http://toto-info.co",proxies = proxy)

    pl = {"options": {"DrawingId": 632, "StartFrom":StartFroms, "Count": 20, "SortField":
"CouponCode", "SortDir": "ASC"}}
    res = s.post(url, headers={'User-Agent':useragent,
                'Accept-Language' : 'ru,en;q=0.8',
                'Accept-Encoding' : 'gzip, deflate, sdch',
                'Connection': 'keep - alive',
                'Content-Type': 'application/json',
                'Host': 'old.toto-info.co',
                'Origin': 'http://toto-info.co',
                'Referer': 'http://toto-info.co/'},proxies = proxy, data=json.dumps(pl))

    data = res.json()

    with open('response.csv', 'w', encoding='utf-8') as file:
        json.dump(data, file, indent=2, ensure_ascii=False)

    print('------------------------------------------')

def main():

    url = 'http://old.toto-info.co/DataService.svc/GetMaxPrizeCoupons'

    useragents = open("useragents.txt").read().split('\n')
    proxies = open("proxies.txt").read().split('\n')

    start = 0 # переменная для хранения точки входа в for
    finish = 1000

    while start < finish:
        try:
            for i in range(start, finish, 20):
              a = (uniform(1, 2))
              sleep(a)
              StartFroms = i
              useragent = "'" + choice(useragents) + "'"
              proxy = {'http': 'http://' + choice(proxies)}
              get_html(url, useragent, proxy, StartFroms)
        except:
            start = i # перезапускаем for c точки исключения

if __name__ == '__main__':
    main()

    


Ответы

Ответ 1



Вот рабочий скрипт. Для теста я указал finish = 100 (чтобы быстрее отработало): import requests from random import choice from time import sleep from random import uniform import csv import json import pandas as pd def get_html(url, useragent, proxy, StartFroms): s = requests.Session() s.get("http://toto-info.co") pl = {"options": {"DrawingId": 632, "StartFrom":StartFroms, "Count": 20, "SortField": "CouponCode", "SortDir": "ASC"}} resp = s.post(url, headers={'User-Agent':useragent, 'Accept-Language' : 'ru,en;q=0.8', 'Accept-Encoding' : 'gzip, deflate, sdch', 'Connection': 'keep - alive', 'Content-Type': 'application/json', 'Host': 'old.toto-info.co', 'Origin': 'http://toto-info.co', 'Referer': 'http://toto-info.co/'},proxies = proxy, data=json.dumps(pl)) return resp.json()['d']['Items'] def main(): url = 'http://old.toto-info.co/DataService.svc/GetMaxPrizeCoupons' useragents = open(r"D:\download\useragents.txt").read().split('\n') proxies = open(r"D:\download\proxies.txt").read().split('\n') start = 0 # переменная для хранения точки входа в for finish = 100 data = [] while start < finish: try: sleep(uniform(1, 2)) useragent = "'{}'".format(choice(useragents)) proxy = {'http': 'http://{}'.format(choice(proxies))} print('processing:\t[{}] ...'.format(start)) data += get_html(url, useragent, proxy, start) start += 20 except Exception as e: print('Exception:\t{}'.format(str(e))) print('building DataFrame ...') df = pd.DataFrame(data) # debug: print first 5 rows of DF... #print(df.head()) out_fn = r'd:/temp/result.xlsx' df.set_index('CouponCode')['Options'] \ .str.extractall(r'\d+-\((.*?)\)')[0] \ .unstack().reset_index().rename_axis(None, 1) \ .to_excel(out_fn, index=False) if __name__ == '__main__': main()

Ответ 2



Взял код автора, немного упростил и получил json. Сам код: import json import requests session = requests.Session() session.get("http://toto-info.co") pl = {"options": {"DrawingId": 632, "StartFrom": 1, "Count": 10, "SortField": "CouponCode", "SortDir": "ASC"}} rs = session.post( url='http://old.toto-info.co/DataService.svc/GetMaxPrizeCoupons', headers={ 'Accept-Language': 'ru,en;q=0.8', 'Accept-Encoding': 'gzip, deflate, sdch', 'Connection': 'keep - alive', 'Content-Type': 'application/json', 'Host': 'old.toto-info.co', 'Origin': 'http://toto-info.co', 'Referer': 'http://toto-info.co/' }, data=json.dumps(pl) ) with open('response.csv', 'w', encoding='utf-8') as f: json.dump(rs.json(), f, indent=2, ensure_ascii=False) После считал json построчно и сохранил в excel: with open('response.csv', mode='r', encoding='utf-8') as f: import xlwt wb = xlwt.Workbook() ws = wb.add_sheet('Json data') for i, line in enumerate(f.readlines()): line = line.rstrip() ws.write(i, 0, line) wb.save('excel.xls') Вот так выглядит excel: Файл с json: { "d": { "Summary": { "TotalCount": 93977, "__type": "SelectSummary:#FonbetEngine.DAL" }, "__type": "SelectResultOfWinCouponSelectSummaryWVcc8KbY:#FonbetEngine.DAL", "Items": [ { "MaxResult": 6, "CouponCode": "10000", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(X); 2-(1); 3-(2); 4-(2); 5-(1); 6-(X); 7-(2); 8-(1); 9-(1); 10-(2); 11-(1); 12-(2); 13-(X); 14-(X); 15-(2)", "TotalStakeValue": 50 }, { "MaxResult": 2, "CouponCode": "100002", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(1); 2-(X); 3-(1); 4-(1); 5-(1); 6-(2); 7-(1); 8-(1); 9-(2); 10-(2); 11-(1); 12-(X); 13-(1); 14-(1); 15-(1)", "TotalStakeValue": 50 }, { "MaxResult": 3, "CouponCode": "100019", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(2); 3-(X); 4-(1); 5-(1); 6-(X); 7-(2); 8-(2); 9-(X); 10-(1); 11-(1); 12-(X); 13-(2); 14-(2); 15-(X)", "TotalStakeValue": 50 }, { "MaxResult": 5, "CouponCode": "100026", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(1); 3-(1); 4-(X); 5-(1); 6-(2); 7-(X); 8-(1); 9-(X); 10-(2); 11-(2); 12-(1); 13-(X); 14-(2); 15-(2)", "TotalStakeValue": 50 }, { "MaxResult": 10, "CouponCode": "100033", "TotalPrizeValue": 961.6088, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(2); 3-(2); 4-(2); 5-(X); 6-(2); 7-(1); 8-(2); 9-(1); 10-(X); 11-(2); 12-(1); 13-(2); 14-(2); 15-(2)", "TotalStakeValue": 50 }, { "MaxResult": 5, "CouponCode": "100040", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(X); 3-(1); 4-(2); 5-(1); 6-(1); 7-(1); 8-(2); 9-(X); 10-(X); 11-(1); 12-(2); 13-(X); 14-(1); 15-(X)", "TotalStakeValue": 50 }, { "MaxResult": 6, "CouponCode": "100057", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(2); 3-(1); 4-(X); 5-(1); 6-(1); 7-(X); 8-(2); 9-(X); 10-(X); 11-(1); 12-(1); 13-(1); 14-(X); 15-(X)", "TotalStakeValue": 50 }, { "MaxResult": 9, "CouponCode": "100064", "TotalPrizeValue": 341.1707, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(1); 3-(X); 4-(1); 5-(X); 6-(1); 7-(X); 8-(2); 9-(X); 10-(1); 11-(2); 12-(1); 13-(1); 14-(2); 15-(1)", "TotalStakeValue": 50 }, { "MaxResult": 4, "CouponCode": "100071", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(2); 3-(1); 4-(1); 5-(2); 6-(X); 7-(1); 8-(1); 9-(2); 10-(1); 11-(X); 12-(1); 13-(2); 14-(2); 15-(1)", "TotalStakeValue": 50 }, { "MaxResult": 5, "CouponCode": "100088", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(1); 2-(2); 3-(2); 4-(1); 5-(1); 6-(X); 7-(2); 8-(2); 9-(X); 10-(1); 11-(1); 12-(2); 13-(1); 14-(X); 15-(X)", "TotalStakeValue": 50 } ] } }

Ответ 3



Трудно найти модуль для обработки табличных данных, который смог бы превзойти Pandas: import json import pandas as pd # если: `data = res.json()`, т.е. `data` - словарь (parsed to dictionary JSON) df = pd.DataFrame(data['d']['Items']) # если `json_str` - строка содержащая JSON response ... #df = pd.DataFrame(json.loads(json_str)['d']['Items']) df.set_index('CouponCode')['Options'] \ .str.extractall(r'\d+-\((.*?)\)')[0] \ .unstack().reset_index().rename_axis(None, 1) \ .to_excel('d:/temp/result.xlsx', index=False) Результат (D:\temp\result.xlsx): "Распарсенный" в DataFrame JSON: In [303]: df Out[303]: Cnt CouponCode MaxResult Options TotalPrizeValue \ 0 1 10000 6 1-(X); 2-(1); 3-(2); 4-(2)... 0.0000 1 1 100002 2 1-(1); 2-(X); 3-(1); 4-(1)... 0.0000 2 1 100019 3 1-(2); 2-(2); 3-(X); 4-(1)... 0.0000 3 1 100026 5 1-(2); 2-(1); 3-(1); 4-(X)... 0.0000 4 1 100033 10 1-(2); 2-(2); 3-(2); 4-(2)... 961.6088 5 1 100040 5 1-(2); 2-(X); 3-(1); 4-(2)... 0.0000 6 1 100057 6 1-(2); 2-(2); 3-(1); 4-(X)... 0.0000 7 1 100064 9 1-(2); 2-(1); 3-(X); 4-(1)... 341.1707 8 1 100071 4 1-(2); 2-(2); 3-(1); 4-(1)... 0.0000 9 1 100088 5 1-(1); 2-(2); 3-(2); 4-(1)... 0.0000 TotalStakeValue __type 0 50 WinCoupon:#FonbetEntity 1 50 WinCoupon:#FonbetEntity 2 50 WinCoupon:#FonbetEntity 3 50 WinCoupon:#FonbetEntity 4 50 WinCoupon:#FonbetEntity 5 50 WinCoupon:#FonbetEntity 6 50 WinCoupon:#FonbetEntity 7 50 WinCoupon:#FonbetEntity 8 50 WinCoupon:#FonbetEntity 9 50 WinCoupon:#FonbetEntity

воскресенье, 16 февраля 2020 г.

Сохранение JSON ответа в сsv. Python

#python #json #python_3x #парсер #csv


В общем сохраняю json ответ в сsv, получается как на картинке.



В итоге хочу достигнуть такой результат. Подскажите как реализовать(желательно с
примером), или литературу какую-нибудь.



Вот сам код.

# -*- coding: utf-8 -*-

import requests
from bs4 import BeautifulSoup
from random import choice
from time import sleep
from random import uniform
import json
import csv

def get_html(url,useragent,proxy,StartFroms):
    #print("get_html")
    #print(StartFroms)
    #print(proxy)
    #print(useragent)
    s = requests.Session()
    s.get("http://toto-info.co",proxies = proxy)

    pl = {"options": {"DrawingId": 632, "StartFrom":StartFroms, "Count": 20, "SortField":
"CouponCode", "SortDir": "ASC"}}
    res = s.post(url, headers={'User-Agent':useragent,
                'Accept-Language' : 'ru,en;q=0.8',
                'Accept-Encoding' : 'gzip, deflate, sdch',
                'Connection': 'keep - alive',
                'Content-Type': 'application/json',
                'Host': 'old.toto-info.co',
                'Origin': 'http://toto-info.co',
                'Referer': 'http://toto-info.co/'},proxies = proxy, data=json.dumps(pl))

    data = res.json()

    with open('response.csv', 'w', encoding='utf-8') as file:
        json.dump(data, file, indent=2, ensure_ascii=False)

    print('------------------------------------------')

def main():

    url = 'http://old.toto-info.co/DataService.svc/GetMaxPrizeCoupons'

    useragents = open("useragents.txt").read().split('\n')
    proxies = open("proxies.txt").read().split('\n')

    start = 0 # переменная для хранения точки входа в for
    finish = 1000

    while start < finish:
        try:
            for i in range(start, finish, 20):
              a = (uniform(1, 2))
              sleep(a)
              StartFroms = i
              useragent = "'" + choice(useragents) + "'"
              proxy = {'http': 'http://' + choice(proxies)}
              get_html(url, useragent, proxy, StartFroms)
        except:
            start = i # перезапускаем for c точки исключения

if __name__ == '__main__':
    main()

    


Ответы

Ответ 1



Вот рабочий скрипт. Для теста я указал finish = 100 (чтобы быстрее отработало): import requests from random import choice from time import sleep from random import uniform import csv import json import pandas as pd def get_html(url, useragent, proxy, StartFroms): s = requests.Session() s.get("http://toto-info.co") pl = {"options": {"DrawingId": 632, "StartFrom":StartFroms, "Count": 20, "SortField": "CouponCode", "SortDir": "ASC"}} resp = s.post(url, headers={'User-Agent':useragent, 'Accept-Language' : 'ru,en;q=0.8', 'Accept-Encoding' : 'gzip, deflate, sdch', 'Connection': 'keep - alive', 'Content-Type': 'application/json', 'Host': 'old.toto-info.co', 'Origin': 'http://toto-info.co', 'Referer': 'http://toto-info.co/'},proxies = proxy, data=json.dumps(pl)) return resp.json()['d']['Items'] def main(): url = 'http://old.toto-info.co/DataService.svc/GetMaxPrizeCoupons' useragents = open(r"D:\download\useragents.txt").read().split('\n') proxies = open(r"D:\download\proxies.txt").read().split('\n') start = 0 # переменная для хранения точки входа в for finish = 100 data = [] while start < finish: try: sleep(uniform(1, 2)) useragent = "'{}'".format(choice(useragents)) proxy = {'http': 'http://{}'.format(choice(proxies))} print('processing:\t[{}] ...'.format(start)) data += get_html(url, useragent, proxy, start) start += 20 except Exception as e: print('Exception:\t{}'.format(str(e))) print('building DataFrame ...') df = pd.DataFrame(data) # debug: print first 5 rows of DF... #print(df.head()) out_fn = r'd:/temp/result.xlsx' df.set_index('CouponCode')['Options'] \ .str.extractall(r'\d+-\((.*?)\)')[0] \ .unstack().reset_index().rename_axis(None, 1) \ .to_excel(out_fn, index=False) if __name__ == '__main__': main()

Ответ 2



Взял код автора, немного упростил и получил json. Сам код: import json import requests session = requests.Session() session.get("http://toto-info.co") pl = {"options": {"DrawingId": 632, "StartFrom": 1, "Count": 10, "SortField": "CouponCode", "SortDir": "ASC"}} rs = session.post( url='http://old.toto-info.co/DataService.svc/GetMaxPrizeCoupons', headers={ 'Accept-Language': 'ru,en;q=0.8', 'Accept-Encoding': 'gzip, deflate, sdch', 'Connection': 'keep - alive', 'Content-Type': 'application/json', 'Host': 'old.toto-info.co', 'Origin': 'http://toto-info.co', 'Referer': 'http://toto-info.co/' }, data=json.dumps(pl) ) with open('response.csv', 'w', encoding='utf-8') as f: json.dump(rs.json(), f, indent=2, ensure_ascii=False) После считал json построчно и сохранил в excel: with open('response.csv', mode='r', encoding='utf-8') as f: import xlwt wb = xlwt.Workbook() ws = wb.add_sheet('Json data') for i, line in enumerate(f.readlines()): line = line.rstrip() ws.write(i, 0, line) wb.save('excel.xls') Вот так выглядит excel: Файл с json: { "d": { "Summary": { "TotalCount": 93977, "__type": "SelectSummary:#FonbetEngine.DAL" }, "__type": "SelectResultOfWinCouponSelectSummaryWVcc8KbY:#FonbetEngine.DAL", "Items": [ { "MaxResult": 6, "CouponCode": "10000", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(X); 2-(1); 3-(2); 4-(2); 5-(1); 6-(X); 7-(2); 8-(1); 9-(1); 10-(2); 11-(1); 12-(2); 13-(X); 14-(X); 15-(2)", "TotalStakeValue": 50 }, { "MaxResult": 2, "CouponCode": "100002", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(1); 2-(X); 3-(1); 4-(1); 5-(1); 6-(2); 7-(1); 8-(1); 9-(2); 10-(2); 11-(1); 12-(X); 13-(1); 14-(1); 15-(1)", "TotalStakeValue": 50 }, { "MaxResult": 3, "CouponCode": "100019", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(2); 3-(X); 4-(1); 5-(1); 6-(X); 7-(2); 8-(2); 9-(X); 10-(1); 11-(1); 12-(X); 13-(2); 14-(2); 15-(X)", "TotalStakeValue": 50 }, { "MaxResult": 5, "CouponCode": "100026", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(1); 3-(1); 4-(X); 5-(1); 6-(2); 7-(X); 8-(1); 9-(X); 10-(2); 11-(2); 12-(1); 13-(X); 14-(2); 15-(2)", "TotalStakeValue": 50 }, { "MaxResult": 10, "CouponCode": "100033", "TotalPrizeValue": 961.6088, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(2); 3-(2); 4-(2); 5-(X); 6-(2); 7-(1); 8-(2); 9-(1); 10-(X); 11-(2); 12-(1); 13-(2); 14-(2); 15-(2)", "TotalStakeValue": 50 }, { "MaxResult": 5, "CouponCode": "100040", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(X); 3-(1); 4-(2); 5-(1); 6-(1); 7-(1); 8-(2); 9-(X); 10-(X); 11-(1); 12-(2); 13-(X); 14-(1); 15-(X)", "TotalStakeValue": 50 }, { "MaxResult": 6, "CouponCode": "100057", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(2); 3-(1); 4-(X); 5-(1); 6-(1); 7-(X); 8-(2); 9-(X); 10-(X); 11-(1); 12-(1); 13-(1); 14-(X); 15-(X)", "TotalStakeValue": 50 }, { "MaxResult": 9, "CouponCode": "100064", "TotalPrizeValue": 341.1707, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(1); 3-(X); 4-(1); 5-(X); 6-(1); 7-(X); 8-(2); 9-(X); 10-(1); 11-(2); 12-(1); 13-(1); 14-(2); 15-(1)", "TotalStakeValue": 50 }, { "MaxResult": 4, "CouponCode": "100071", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(2); 2-(2); 3-(1); 4-(1); 5-(2); 6-(X); 7-(1); 8-(1); 9-(2); 10-(1); 11-(X); 12-(1); 13-(2); 14-(2); 15-(1)", "TotalStakeValue": 50 }, { "MaxResult": 5, "CouponCode": "100088", "TotalPrizeValue": 0, "__type": "WinCoupon:#FonbetEntity", "Cnt": 1, "Options": "1-(1); 2-(2); 3-(2); 4-(1); 5-(1); 6-(X); 7-(2); 8-(2); 9-(X); 10-(1); 11-(1); 12-(2); 13-(1); 14-(X); 15-(X)", "TotalStakeValue": 50 } ] } }

Ответ 3



Трудно найти модуль для обработки табличных данных, который смог бы превзойти Pandas: import json import pandas as pd # если: `data = res.json()`, т.е. `data` - словарь (parsed to dictionary JSON) df = pd.DataFrame(data['d']['Items']) # если `json_str` - строка содержащая JSON response ... #df = pd.DataFrame(json.loads(json_str)['d']['Items']) df.set_index('CouponCode')['Options'] \ .str.extractall(r'\d+-\((.*?)\)')[0] \ .unstack().reset_index().rename_axis(None, 1) \ .to_excel('d:/temp/result.xlsx', index=False) Результат (D:\temp\result.xlsx): "Распарсенный" в DataFrame JSON: In [303]: df Out[303]: Cnt CouponCode MaxResult Options TotalPrizeValue \ 0 1 10000 6 1-(X); 2-(1); 3-(2); 4-(2)... 0.0000 1 1 100002 2 1-(1); 2-(X); 3-(1); 4-(1)... 0.0000 2 1 100019 3 1-(2); 2-(2); 3-(X); 4-(1)... 0.0000 3 1 100026 5 1-(2); 2-(1); 3-(1); 4-(X)... 0.0000 4 1 100033 10 1-(2); 2-(2); 3-(2); 4-(2)... 961.6088 5 1 100040 5 1-(2); 2-(X); 3-(1); 4-(2)... 0.0000 6 1 100057 6 1-(2); 2-(2); 3-(1); 4-(X)... 0.0000 7 1 100064 9 1-(2); 2-(1); 3-(X); 4-(1)... 341.1707 8 1 100071 4 1-(2); 2-(2); 3-(1); 4-(1)... 0.0000 9 1 100088 5 1-(1); 2-(2); 3-(2); 4-(1)... 0.0000 TotalStakeValue __type 0 50 WinCoupon:#FonbetEntity 1 50 WinCoupon:#FonbetEntity 2 50 WinCoupon:#FonbetEntity 3 50 WinCoupon:#FonbetEntity 4 50 WinCoupon:#FonbetEntity 5 50 WinCoupon:#FonbetEntity 6 50 WinCoupon:#FonbetEntity 7 50 WinCoupon:#FonbetEntity 8 50 WinCoupon:#FonbetEntity 9 50 WinCoupon:#FonbetEntity

воскресенье, 9 февраля 2020 г.

Pandas при чтении CSV файла не парсит числа, содержащие запятую в качестве десятичного разделителя

#python #парсер #pandas #csv #dataframe


Файл csv сохранен в LibreOffice из excel файла. При стандартной загрузке:

map_data = pd.read_csv('map.csv', sep=';')


в нужном столбце получаются данные типа - dtype: object
Если попытаться их перевести в числовые:

pd.to_numeric(map_data['Dist_Loc'])


выдается следующая ошибка:

ValueError: Unable to parse string "3,095" at position 0


Если попытаться перевести в числовые другим способом:

map_data['Dist_Loc'].astype(np.float)


Тоже возникает ошибка:

ValueError: could not convert string to float: '6,157'

    


Ответы

Ответ 1



Если 6,157 - это 6.157, т.е. , - десятичный разделитель, то можно воспользоваться параметром decimal df = pd.read_csv('map.csv', sep=';', decimal=',') если , это разделитель разрядов и 6,157 - это 6157, то можно воспользоваться параметром thousands: df = pd.read_csv('map.csv', sep=';', thousands=',') Ссылка на документацию... Pandas также замечательно читает напрямую из Excel: df = pd.read_excel(filename)

среда, 5 февраля 2020 г.

Pandas дописывание в конец CSV файла

#python #pandas #csv #dataframe


Есть вот такой csv файл

,Date,Model,Mark
0,2019-02-15,Q2612X,HP
1,2019-02-15,TK-1150,Kyocera
2,2019-02-15,MP2000,Ricoh
3,2019-02-26,CE255X,HP


Дописываю в конец файла

import pandas as pd

columns = ['Date', 'Model', 'Mark']

data = [
['2019-02-28', 'Q2612X', 'HP']
]
df = pd.DataFrame(data, columns=columns)
df.to_csv(r'cart.csv', mode='a', header=False)


Строка дописывается

,Date,Model,Mark
0,2019-02-15,Q2612X,HP
1,2019-02-15,TK-1150,Kyocera
2,2019-02-15,MP2000,Ricoh
3,2019-02-26,CE255X,HP
0,2019-02-28,Q2612X,HP


Но индекс принимает нулевое значение. Подскажите как реализовать продолжение индекса.
    


Ответы

Ответ 1



Проще всего отказаться от записи индекса вообще: df.to_csv(..., index=False) При чтении такого CSV файла Pandas автоматически создаст индекс, начинающийся с нуля.

Ответ 2



Вы можете изменить значение индекса в вашем df так: df.index = [4,] Если вы не знаете какое значение присваивать, то нужно посчитать строки в файле. Можно так: with open('test.csv') as f: lines_count = sum(1 for _ in f) - 1

среда, 22 января 2020 г.

Вывод определенных столбцов из csv

#python #python_3x #csv


Есть сsv файл с именованными колонками вида:

id;name;address;zip
1;vasya;moscow;11111
2;oleg;sochi;22222


Как мне с помощью стандартного модуля csv вывести только столбцы к примеру name и
zip? В дальнейшем необходимо сформировать новый csv файл только с этими двумя колонками.
    


Ответы

Ответ 1



Решил, может кому пригодится: import csv with open('f_name', 'r') as f: incl_col = [1, 3] # индексы нужных столбцов new_csv = [] # новый список для нового файла reader = csv.reader(f, delimiter=";") for row in reader: col = list(row[i] for i in incl_col) print(col) # вывод нужных столбцов new_csv.append(col) # заполняем новый список нужными столбцами with open('new.csv', 'w') as f: # создаем новый файл writer = csv.writer(f, delimiter=";") writer.writerows(new_csv)

пятница, 10 января 2020 г.

Загрузить файл csv через php

#php #csv


При нажатии на кнопку необходимо сформировать и загрузить файл с данными в формате csv.

Есть такая функция function getCsvFile(...)

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

Подскажите, пожалуйста, что не так.

Заранее благодарен

$now = gmdate("D, d M Y H:i:s");
header("Cache-Control: max-age=0, no-cache, must-revalidate, proxy-revalidate");
header("Last-Modified: {$now} GMT");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Disposition: attachment;filename=test.csv");
header("Content-Transfer-Encoding: binary");

//$array = $this->getLinks(...);
$titles = array("id", "Test");
ob_start();
$df = fopen("test.csv", "w");
fputcsv($df, $titles, ';');

$data = array(
          array(1,2),
          array(1,2),
          array(1,2),
          array(1,3)
        );

foreach ($data as $row) {
   fputcsv($df, $row, ';');
}
fclose($df);

    


Ответы

Ответ 1



По идее Content-Type должен быть один. И в значении для csv надо указать text/csv header("Content-type: text/csv"); Пример - тут.

Ответ 2



Разобрался. Возможно частично проблема была связана с заголовками, но также с запуском самой функции. У меня эта функция запускается через ajax, поэтому необходимо было при передаче значений дополнительно добавить success: function(data) { document.location.href="..."; }

Как на Java записать символы валют в CSV файл для корректного импорта в Excel

#java #excel #csv


При импорте получившегося CSV файла в Excel знаки валют, кроме € и $ заменяются на
?. В Notepad++ все отображается нормально.

String data = "$,€,₪,₴,zł,kr,£,..."

String fileName = "C:\\Program Files\\Java\\apache-tomcat-7.0.68\\temp\\testCSV.csv";

String uncode = "UTF-8";

//uncode = "UTF-8", "UTF-16", "UTF-16BE", "UTF-16LE", "Cp866", "Cp1251", "US-ASCII",
"ISO-8859-1";


Пробовал разные варианты:


FileWriter out = new FileWriter(fileName);
OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(fileName),uncode);
PrintWriter out = new PrintWriter(fileName, uncode));
PrintWriter out = new PrintWriter (new OutputStreamWriter (new FileOutputStream (fileName),
uncode));
Writer out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName),
uncode));
:

File f = new File(fileName);
FileUtils.writeStringToFile(f, data, uncode);
out.append(data);
//out.write(data); //out.println(data);



В чем может быть проблема?
    


Ответы

Ответ 1



Я могу ошибаться, но насколько помню, MS Excel не распознает UTF-8 без BOM (Byte Order Mark), т.ч. попробуйте как-то так: BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream("file.txt", true), "utf8")); writer.append('\uFEFF'); writer.append("мама мыла раму"); Проверка » /usr/bin/printf "\ufeff...\n" | file file.txt file.txt: UTF-8 Unicode (with BOM) text, with no line terminators В то же время, большинству текстовых редакторов BOM не интересен, поэтому в них у вас текст отображается нормально.

воскресенье, 5 января 2020 г.

Чтение и обработка огромных файлов CSV

#python #pandas #csv #big_data


Есть 2 файла в формате .csv, размеры 60 ГБ и 1 ГБ. Мне необходимо создать на их основе
таблицу по ключам из обоих файлов (по типу WHERE и JOIN в SQL), а затем экспортировать
опять в файл .csv. Как мне это сделать? pandas такое не сможет обработать скорее всего,
просто оперативки не хватит. 
    


Ответы

Ответ 1



Можно воспользоваться Dask DataFrame вместо Pandas. Dask умеет обрабатывать DataFrame на диске - т.е. такие, которые не помещаются в память. Обычно Dask работает гораздо медленнее Pandas и его API гораздо беднее. Кроме этого можно прочитать в память только те столбцы, которые участвуют в объединении и фильтрации (если эти данные влезают в память), выбрать только соответствующие строки и дальше читать из CSV файлов только соответствующие строки. Но проще всего для данных задач использовать базы данных, например MySQL или PostgreSQL - они с легкостью обрабатывают данные, которые не помещаются в памяти. Кроме этого они поддерживают индексацию, что может значительно ускорить обработку данных. Кстати в большинстве БД существуют специальные утилиты для быстрой загрузки CSV файлов в БД: PostgreSQL: COPY, MySQL: LOAD DATA

четверг, 2 января 2020 г.

Чтение и перезапись больших файлов csv

#python #pandas #dataframe #csv


Прошу совета. У меня есть большое число csv файлов с данными по котировкам (180 Гб),
Вкаждом файле лежат данные за 1 день по типу ticker, цена1, цена2.
Пример: за 13082008.csv лежит:

A 1 2 3 4
A 2 2 2 2
A 3 4 5 6
B 1 1 1 1
B 2 3 3 3
C 1 1 1 1
C 1 1 1 1


Я хочу перенести данные из этих файлов в новые CSV так, чтобы у меня лежали данные
по каждому тикеру. То есть по примеру у меня создадутся файлы A.csv B.csv C.csv. У
меня есть решение, но оно довольно медленное, я открываю 13082008.csv, вписываю его
в датафрейм, прохожусь по строкам и записываю каждую строку в нужный файл. 

Не посоветуете решение, которое будет намного быстрее? 

Пример моего кода:

def read_and_rewrite_options(path_out, folder, options):

import pandas as pd
import os
import csv   
header = ['UnderlyingSymbol', 'UnderlyingPrice', 'Exchange', 'OptionSymbol', 'OptionExt',
'Type', 'Expiration', 'DataDate', 
                  'Strike', 'Last', 'Bid', 'Ask', 'Volume', 'OpenInterest', 'IV',
'Delta', 'Gamma', 'Theta', 'Vega', 'AKA']
print('folder: ' + folder)
for ops in options:
    data = read_l2_file(path_out + folder + '/' + ops)
    for index, row in data.iterrows():
        #print(row['UnderlyingSymbol'])
        path = path_in + options_folder + 'options_' + row['UnderlyingSymbol'] + '.csv'
                  # df = df.append({'symbol' : row['symbol'], 'quotedate' : row['quotedate'],
'open' : row['open'] , 'high' : row['high'], 
       #                 'low' : row['low'], 'close' : row['close'], 'volume' : row['volume'], 
       #                 'adjustedclose' : row['adjustedclose']}, ignore_index = True)
        if row['UnderlyingSymbol'] + '.csv' not in os.listdir(path_in + options_folder):    
            with open(path, 'a', newline='') as f:
                writer = csv.writer(f)
                writer.writerow(header)
                writer.writerow(row)
        else:
             with open(path, 'a', newline='') as f:
                writer = csv.writer(f)
                writer.writerow(row)
    print('options by ' + ops + ' are written')
print('---------------------------------------------')


(Тут считываю данные за месяц)
    


Ответы

Ответ 1



Мне кажется @Akina дал очень дельный совет - можно сохранить все данные в одну SQL таблицу с индексами ("date", "symbol") и далее выбирать по индексу нужные данные. Это можно сделать приблизительно так: import pandas as pd from sqlalchemy import create_engine from pathlib import Path engine = create_engine('sqlite:///c:/temp/stock.db') conn = engine.connect() path = Path(r"/path/to/data_directory") for f in path.glob("*.csv"): df = pd.read_csv(f, ...) df.set_index(["Date", "Symbol"]).to_sql("stocks", conn, if_exists="append", index=True) после этого вы можете читать данные следующим образом: df = pd.read_sql("select * from stocks where symbol == 'AAPL'", conn) PS вместо SQLite можно использовать любую БД, которую поддерживает SQL Alchemy. рабочий пример с данными из Yahoo Finance: import pandas as pd import pandas_datareader.data as web from sqlalchemy import create_engine engine = create_engine('sqlite:///c:/temp/stocks.db') conn = engine.connect() f = web.DataReader(['IBM', 'GOOG', 'AAPL'], 'yahoo', '2001-01-01', '2019-01-01') получим следующий датасет: In [42]: f.stack() Out[42]: Attributes High Low Open Close Volume Adj Close Date Symbols 2001-01-02 AAPL 1.089286 1.040179 1.062500 1.062500 113078000.0 0.930781 IBM 87.500000 84.125000 84.500000 84.812500 8007200.0 57.459831 2001-01-03 AAPL 1.191964 1.031250 1.035714 1.169643 204268400.0 1.024641 IBM 95.000000 83.750000 83.750000 94.625000 12769900.0 64.107704 2001-01-04 AAPL 1.321429 1.200893 1.295759 1.218750 184849000.0 1.067660 IBM 99.750000 92.687500 94.750000 93.187500 15420500.0 63.133808 2001-01-05 AAPL 1.241071 1.147321 1.209821 1.169643 103089000.0 1.024641 ... ... ... ... ... ... ... 2018-12-27 IBM 113.779999 109.470001 109.989998 113.779999 6045600.0 111.149292 2018-12-28 AAPL 158.520004 154.550003 157.500000 156.229996 42291400.0 154.966034 GOOG 1055.560059 1033.099976 1049.619995 1037.079956 1414800.0 1037.079956 IBM 114.800003 112.500000 114.220001 113.029999 5117500.0 110.416634 2018-12-31 AAPL 159.360001 156.479996 158.529999 157.740005 35003500.0 156.463837 GOOG 1052.699951 1023.590027 1050.959961 1035.609985 1493300.0 1035.609985 IBM 114.349998 112.419998 113.330002 113.669998 4982800.0 111.041840 запишем его в SQLite DB: f.stack().to_sql("stock", conn, if_exists="append", index=True) conn.close() выбираем данные по индексу из БД: engine = create_engine('sqlite:///c:/temp/stocks.db') conn = engine.connect() df = pd.read_sql("select * from stock where symbols == 'AAPL' and date between '2018-01-01' and '2018-12-31'", conn) результат: In [46]: df Out[46]: Date Symbols High Low Open Close Volume Adj Close 0 2018-01-02 00:00:00.000000 AAPL 172.300003 169.259995 170.160004 172.259995 25555900.0 168.339050 1 2018-01-03 00:00:00.000000 AAPL 174.550003 171.960007 172.529999 172.229996 29517900.0 168.309738 2 2018-01-04 00:00:00.000000 AAPL 173.470001 172.080002 172.539993 173.029999 22434600.0 169.091522 3 2018-01-05 00:00:00.000000 AAPL 175.369995 173.050003 173.440002 175.000000 23660000.0 171.016678 4 2018-01-08 00:00:00.000000 AAPL 175.610001 173.929993 174.350006 174.350006 20567800.0 170.381485 5 2018-01-09 00:00:00.000000 AAPL 175.059998 173.410004 174.550003 174.330002 21584000.0 170.361954 6 2018-01-10 00:00:00.000000 AAPL 174.300003 173.000000 173.160004 174.289993 23959900.0 170.322845 .. ... ... ... ... ... ... ... ... 243 2018-12-19 00:00:00.000000 AAPL 167.449997 159.089996 166.000000 160.889999 49047300.0 159.588348 244 2018-12-20 00:00:00.000000 AAPL 162.110001 155.300003 160.399994 156.830002 64773000.0 155.561188 245 2018-12-21 00:00:00.000000 AAPL 158.160004 149.630005 156.860001 150.729996 95744600.0 149.510544 246 2018-12-24 00:00:00.000000 AAPL 151.550003 146.589996 148.149994 146.830002 37169200.0 145.642090 247 2018-12-26 00:00:00.000000 AAPL 157.229996 146.720001 148.300003 157.169998 58582500.0 155.898438 248 2018-12-27 00:00:00.000000 AAPL 156.770004 150.070007 155.839996 156.149994 53117100.0 154.886688 249 2018-12-28 00:00:00.000000 AAPL 158.520004 154.550003 157.500000 156.229996 42291400.0 154.966034 [250 rows x 8 columns]

Ответ 2



Решение в лоб через grep. Бысрее наверное только в индексируемой БД: grep -rh "^A" /path/with/csv/ > A.csv

Ответ 3



Я не настоящий сварщик, но если условие без использования БД, вот мой вариант фильтрации силами только pandas: import pandas as pd if __name__ == '__main__': files = ['1.csv', '2.csv', ...] chunksize = 10 ** 6 for file in files: for chunk in pd.read_csv(file, chunksize=chunksize, header=None, delimiter=' ', names=['ticker', 'num1', 'num2', 'num3', 'num4']): tickers = chunk.ticker.unique() for ticker in tickers: target = chunk[chunk.ticker == ticker] target.to_csv(f'out/{ticker}.csv', mode='a', header=False, index=False, sep=' ') За исходный формат взят формат файла в вопросе. chunksize настраивается в зависимости от доступной памяти, можно и без него, если все исходные файлы небольшие по размеру. Тогда просто chunk = pd.read_csv(...) и дальше по коду без изменений.

среда, 1 января 2020 г.

Ошибка: pandas.errors.ParserError: Error tokenizing data. C error: Expected 1 fields in line 5, saw 9

#python #pandas #dataframe #csv


Пытаюсь зугрузить tsv–файл в pandas.

import pandas as pd
df = pd.read_csv(filename, sep='\t')
print(df)


После выполнения этого кода в консоли вижу ошибку

df = pd.read_csv(filename, sep='\t') File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/io/parsers.py",
line 655, in parser_f
return _read(filepath_or_buffer, kwds) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/io/parsers.py",
line 411, in _read
data = parser.read(nrows) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/io/parsers.py",
line 982, in read
ret = self._engine.read(nrows) File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/pandas/io/parsers.py",
line 1719, in read
data = self._reader.read(nrows) File "pandas/_libs/parsers.pyx", line 890, in pandas._libs.parsers.TextReader.read
(pandas/_libs/parsers.c:10862) File "pandas/_libs/parsers.pyx", line 912, in pandas._libs.parsers.TextReader._read_low_memory
(pandas/_libs/parsers.c:11138) File "pandas/_libs/parsers.pyx", line 966, in pandas._libs.parsers.TextReader._read_rows
(pandas/_libs/parsers.c:11884) File "pandas/_libs/parsers.pyx", line 953, in pandas._libs.parsers.TextReader._tokenize_rows
(pandas/_libs/parsers.c:11755) File "pandas/_libs/parsers.pyx", line 2184, in pandas._libs.parsers.raise_parser_error
(pandas/_libs/parsers.c:28765) pandas.errors.ParserError: Error tokenizing data. C
error: Expected 1 fields in line 5, saw 9


Подскажите, в чем может быть проблема?
    


Ответы

Ответ 1



Обычно эта ошибка говорит о том, что CSV/TSV файл "поломан", т.е. не является корректным CSV/TSV файлом. Иногда это случается, когда некоторые программы пишут в заголовок CSV/TSV файла техническую информацию или описание. В этом случае часто используют символ комментирования, например # в начале строки. Pandas умеет игнорировать закомментированные строки: pd.read_csv(filename, sep='\t', comment='#')

Ответ 2



Скорее всего ошибка в том, что в файле данные разбиты не верно (например, перед данными идет заголовок). Когда pandas пытается разобрать файл, библиотеке надо понять сколько создавать столбцов, и если в первых строках количество элементов данных отличается от последующих, то будет возникать ошибка. Я знаю про два решения. Игнорировать ошибку. pd.read_csv(filename, sep='\t', error_bad_lines=False) В этом случае таблица будет создана на основе первой строки и все, что не подойдет подойдет под ее формат будет опущено. Подойдет, если у вас идут данные с первой строки, но где–то в файле могут «слететь» данные. Пропустить заголовок pd.read_csv(filename, sep='\t', skiprows=N) В этом случае вы пропустите первые N строк файла, начав с N+1. Подходит для работы с файлами, в которых есть заголовки.

понедельник, 30 декабря 2019 г.

Нахождение max() и min() в столбце CSV файла

#python #python_3x #список #матрицы #csv


Дан файловый объект .txt, в котором данные приведены как числа:


  Rosneft,07/19/06,00:00,220.32,220.32,203.03,203.95,51774,0


Таких данных около 2 тыс. и все они записаны в файле с новой строки.
Нужно найти максимальную и минимальную цену и ее дату в файле.  

file = open('file.txt') # Открыть файл
for line in file: # Пройти циклом 
    new_line1 = line.split(',') #разделить строки по запятым в new_line1
    new_file1 = new_line1[4:6] # срезать нужные строки  


И на этом логика выполнения задачи зашла в тупик. Хотелось бы понять эту логику в
примерах как с ф-цией min() и max(), так и без неё.
    


Ответы

Ответ 1



Решение без использования доп. модулей: Файл с данными (C:\Temp\data.csv): Rosneft,07/19/06,00:00,220.32,220.32,203.03,203.95,51774,0 Rosneft,07/20/06,00:00,230.33,230.34,230.35,230.36,56544,0 Rosneft,07/21/06,00:00,210.33,210.34,210.35,210.36,50344,0 Решение: filename = r'C:\Temp\data.csv' data = [] with open(filename) as f: for line in f: tmp = line.split(',') tmp[3:] = list(map(float, tmp[3:])) data.append(tmp) def transpose(matrix): return list(zip(*matrix)) def get_min_idx(data, col_idx=0): return min(range(len(data)), key=transpose(data)[col_idx].__getitem__) def get_max_idx(data, col_idx=0): return max(range(len(data)), key=transpose(data)[col_idx].__getitem__) print('Min:\t', data[get_min_idx(data, col_idx=3)]) print('Max:\t', data[get_max_idx(data, col_idx=3)]) Результат: Min: ['Rosneft', '07/21/06', '00:00', 210.33, 210.34, 210.35, 210.36, 50344.0, 0.0] Max: ['Rosneft', '07/20/06', '00:00', 230.33, 230.34, 230.35, 230.36, 56544.0, 0.0]

Ответ 2



Для обработки табличных (2D) данных идеально подходит модуль Pandas. Пример: создадим тестовый файл похожей структуры, в качестве данных возьмем котирови Apple начиная с 2001-го года (4490 строк) import pandas as pd # pip install pandas from pandas_datareader.data import DataReader # pip install pandas-datareader df = DataReader('AAPL', 'yahoo', '2001-01-01', '2018-11-06').reset_index() df.to_csv('c:/temp/data.csv', index=False) Несколько строк из файла: Date,High,Low,Open,Close,Volume,Adj Close 2001-01-02,1.0892857313156128,1.0401785373687744,1.0625,1.0625,113078000.0,0.713999330997467 2001-01-03,1.1919642686843872,1.03125,1.0357142686843872,1.1696428060531616,204268400.0,0.7859991192817688 2001-01-04,1.3214285373687744,1.2008928060531616,1.2957571744918823,1.21875,184849000.0,0.818999171257019 2001-01-05,1.2410714626312256,1.1473214626312256,1.2098214626312256,1.1696428060531616,103089000.0,0.7859991192817688 2001-01-08,1.2131643295288086,1.1383928060531616,1.2098214626312256,1.1830357313156128,93424800.0,0.7949992418289185 Решение: import pandas as pd df = pd.read_csv(r'c:/temp/data.csv') поиск строк с наименьшим и наибольшим значением в поле Adj Close: In [27]: print(df.nsmallest(1, ['Adj Close'])) Date High Low Open Close Volume Adj Close 573 2003-04-17 0.946429 0.908571 0.942857 0.937143 154064400.0 0.629759 In [28]: print(df.nlargest(1, ['Adj Close'])) Date High Low Open Close Volume Adj Close 4466 2018-10-03 233.470001 229.779999 230.050003 232.070007 28654800.0 232.070007 TOP 5 значений: In [29]: print(df.nlargest(5, ['Adj Close'])) Date High Low Open Close Volume Adj Close 4466 2018-10-03 233.470001 229.779999 230.050003 232.070007 28654800.0 232.070007 4465 2018-10-02 230.000000 226.630005 227.250000 229.279999 24788200.0 229.279999 4445 2018-09-04 229.179993 226.630005 228.410004 228.360001 27390100.0 228.360001 4467 2018-10-04 232.350006 226.729996 230.779999 227.990005 32042000.0 227.990005 4444 2018-08-31 228.869995 226.000000 226.509995 227.630005 43340100.0 227.630005

Ответ 3



Логика такова: line="Rosneft,07/19/06,00:00,220.32,220.32,203.03,203.95,51774,0" elems=line.split(',') date=elems[1] prices = list(map(float,elems[3:7])) print("На {} максимум: {}, минимум: {}".format(date, max(prices), min(prices))) На выходе: На 07/19/06 максимум: 220.32, минимум: 203.03

суббота, 21 декабря 2019 г.

Как найти ключевые слова в тексте одного столбца DataFrame?

#python #регулярные_выражения #pandas #dataframe #csv


у меня есть файл CSV я его прочитал, импортировал библиотеки
мне необходимо найти ключевые слова в тексте одного столбца: 

вот эти критерии, отдельно:

/city/directory/<цифры или буквы>.html

/good/<цифры>/owner_info

/bulletin/<цифры> 


и пользователь у которого совпадали эти 3 критерии совместно

мой код

import pandas as pd
import numpy as np
import re

exp = pd.read_csv(r'C:\Users\4X\Desktop\pandas\study\...csv')

re.findall('(?:/good/)|(?:/owner_info)', '/good/<цифры>/owner_info?')
exp.query('url == @card_filte')


здесь все отрабатывает

а вот со вторым и третьим не работает

contacs1 = re.findall(r'(?:/good/)|(?:/owner_info)', '/good/<цифры>/owner_info?')
exp.query('url == @contacs1_filte')

contacs2 = re.findall(r'(?:/bulletin/)', '/bulletin/<цифры>')
exp.query('url == @contacs1_filte')

    


Ответы

Ответ 1



Для того чтобы искать в столбце используя регулярные выражения можно воспользоваться pandas.Series.str.contains(): mask = df["column_name"].str.contains(r"") res = df.loc[mask] PS если в вопросе будет приведен пример данных и ожидаемый результат, то я дополню вопрос примером, с использованием ваших данных...

среда, 11 декабря 2019 г.

Конвертация большого CSV в XLS

#php #excel #csv


В кастомной CMS есть возможность скачать рабочие данные в формате Excel. Сейчас это
происходит через вызов внешнего конвертера CSV → XLS. Никакого стилевого оформления
данных нет и не требуется, это просто аналог csv в более понятном для клиентов виде.
Хочется заменить внешний конвертер на что-нибудь родное для PHP.  

Посоветуйте библиотеку или просто подход, исходя из личного опыта. Подчеркиваю, что
данных бывает много! PHPExcel не предлагайте, пожалуйста. Он на больших объемах кушает
слишком много памяти. 
    


Ответы

Ответ 1



Я бы не стал писать отдельный ответ, но вы отметили что оформление вас не интересует. Чтож, мне кажется вам надо разбить задачу на 2 части: 1) Генерация данных по кусочкам - каждый кусок должен быть такого размера, чтобы ваш PHP (с вашими ограничениями по памяти, ресурсам процессора и прочим настройкам) мог спокойно обработать его. 2) Собственно запись данных из конкретного кусочка всей информации в файл. Исходя из такого подхода, вы можете запустить некий цикл/очередь, и по очереди обработать любое нужное вам количество информации (!). А затем собственно сконвертировать в формат Excel. Вы конечно же можете использовать вышеозвученный CSV формат, а затем конвертировать его в Excel. Однако, я могу предложить лучшую альтернативу - формат XML (XML Spreadsheet 2003) или Open XML. Для использования этого формата вовсе не обязательно использовать ту же библиотеку PHPExcel, вы можете написать и собственный код, так как вас не интересует оформление, и поэтому большая часть функций PHPExcel вам вообще не нужна. Что вам нужно это вручную создать нужную структуру формата файла в XML, и в цикле выдавать в него значения из кусочков (file append). В итоге, после завершения обработки всех данных вы получите файл в формате .XLSX и ваш клиент спокойно сможет открыть его в Excel. В результате у вас получится что-то вроде этого: Author Author 2015-04-19T21:57:54Z 14.00 9264 20100 0 24 False False Column 1 Column 2 Row 1 Row 2
Собственно, если вы решите пойти таким путём - вы можете поискать в Гугле по запросам "OpenXML generate Excel" и посмотреть как это делается в разных языках (не только через PHP). Учитывая отсутствие оформления - большая часть проблем у вас будет не с генерацией контента, или конвертированием в XML, а в том чтобы создать исходный шаблон и добиться того, чтобы Excel открывал его правильно.

Ответ 2



Не совсем техническое решение, но из личного опыта - уберите конвертер и отдавайте клиентам файл с расширением CSV по кнопке "Экспорт в Excel". Excel выставляет ассоциации с CSV по умолчанию. У файлов показывается экселевский значок - вобщем, для окончательного пользователя файл ничем не отличим от XLS. Особенно если отображение расширений отключено (опять же, по умолчанию).

Ответ 3



Читать потоково. Писать потоково: PHP_XLSXWriter P.S. Но вообще я бы прислушался к совету @PashaPash и не городил велосипед. CSV прекрасно открывается Экселем.

суббота, 7 декабря 2019 г.

Как сравнить два csv файла

#c_sharp #csv #сравнение


Есть 2 csv файла с содержимым

1.csv

spain;russia;japan
italy;russia;france


2.csv

spain;russia;japan
india;iran;pakistan


Считываю оба файла и заношу их содержимое в список

var lst1= File.ReadAllLines("1.csv").ToList();
var lst2= File.ReadAllLines("2.csv").ToList();


Затем я ищу уникальные элементы из обоих списков

var rezList = lst1.Except(lst2).Union(lst2.Except(lst1)).ToList();


В rezlist у нас следюущие данные.

[0] = "italy;russia;france"
[1] = "india;iran;pakistan"


Теперь же я хочу сравнить оба csv-файла по второй и третьей колонке. Как мы выдими
разделители колонок у нас ;

class StringLengthEqualityComparer : IEqualityComparer
    {

        public bool Equals(string x, string y)
        {
            return (x.Split(';')[1] == y.Split(';')[1] && x.Split(';')[2] == y.Split(';')[2]);
        }

        public int GetHashCode(string obj)
        {
            return obj.Split(';')[1].GetHashCode();
        }
    }

 StringLengthEqualityComparer stringLengthComparer = new StringLengthEqualityComparer();
 var rezList = lst1.Except(lst2,stringLengthComparer ).Union(lst2.Except(lst1,stringLengthComparer),stringLengthComparer).ToList();


Вопрос. Как правильно составить класс StringLengthEqualityComparer чтобы он искал
уникальные значения по двум колонкам?
    


Ответы

Ответ 1



Интерфейс IEqualityComparer предоставляет возможность расширения или замены логики сравнения объектов. Он используется, например, в таких структурах, как Dictionary и HashSet, а также в некоторых методах, которые активно пользуются сравнением объектов (как например использованный вами метод расширения Except()). Как известно, для того, чтобы иметь возможность корректно сравнивать объекты, в них должны быть переопределены методы Equals() и GetHashCode(), причем должны соблюдаться следующие условия: стандартные условия для равенства (например, транзитивность) два равных объекта должны давать одинаковое значение хэшкода (При этом два разных объекта могут иметь равные хэшкоды -- это называется коллизией и должно случаться как можно реже.) Оба этих метода активно используются структурами Dictionary, HashSet, а также внутренним классом Set, который используется в методе Except(). В случае, когда мы не хотим или не имеем возможности изменять логику сравнения для существующих типов, на помощь нам и приходит интерфейс IEqualityComparer -- вместо вызовов методов Equals() и GetHashCode() у самих объектов, эти методы вызываются у компаратора. Именно поэтому этот интерфейс содержит оба метода, а не один Equals(). А также именно поэтому реализация компаратора должна соблюдать обозначенные выше условия. Приведенная вами реализация компаратора дает корректные результаты сравнения, однако при большом объеме данных может свести на нет все преимущества быстрой работы метода Except(). Для пар a;b и a;c выдастся одинаковый хэшкод, они попадут в одну корзину внутри Set, что ухудшает показатели скорости работы (подробнее читайте в статьях о том, как работают хэш-таблицы). Поэтому правильная реализация должна использовать те же поля, которые используются в Equals(), т.е. колонки 1 и 2 (про хэш-функции также читайте в статьях о хэш-таблицах). Например: public int GetHashCode(string obj) { var valuesArray = obj.Split(';') int hashcode = valuesArray[1].GetHashCode(); hashcode = hashcode * 31 + valuesArray[2].GetHashCode(); return hashcode; } На этом реализация компаратора закончена. Однако в целом производительность такого решения оставляет желать лучшего. Поскольку вы вызываете Except() дважды, то для каждой пары строк из обоих файлов методы компаратора (по крайней мере, GetHashCode()) будут вызываться дважды. Вкупе с избыточными разбиениями внутри этих методов картина получается нерадостная. Можно пойти по другому пути, например, заранее разбить строки: var splittedLst1 = lst1.Select(i => i.Split(';')); var splittedLst2 = lst2.Select(i => i.Split(';')); Затем получить разницу: var comparer = new StringLengthEqualityComparer(); var rezList = splittedLst1 .Except(splittedLst2, comparer) .Union(splittedLst2.Except(splittedLst1, comparer)); А при необходимости снова склеить строки: foreach (var item in rezList) { Console.WriteLine(string.Join(";", item)); } При таком подходе каждая строка будет разбита всего один раз, а код компаратора упростится: class StringLengthEqualityComparer : IEqualityComparer { public bool Equals(string[] x, string[] y) { return x[1] == y[1] && x[2] == y[2]; } public int GetHashCode(string[] obj) { var hashcode = obj[1].GetHashCode(); hashcode = hashcode * 31 + obj[2].GetHashCode(); return hashcode; } } Если вы ожидаете строки разной длины (в смысле количества колонок), то нужно изменить компаратор таким образом, чтобы он корректно работал со строками разной длины. Провел небольшой тест для сравнения производительности. В качестве тестовых данных склеил 10000 раз приведенные вам двухстрочники. Разница в результатах при этом получилась следующая: Radzhab: 332ms andreycha: 63ms

Ответ 2



Как уже написали в комментариях, лучше отказаться от IEqualityComparer, т.к., имхо, это попытка заставить кота лаять. У нас единицы информации — это "ячейки", т.е. слова конкретные, оперирование строками с этими словами порождает неудобные и багоопасные конструкции с прямым индексированием (кстати, легковесное в теории сравнение превратилось в 4-кратный вызов разбиения строки на подмассив; даже по алгоритму достаточно двух раз), что собственно ни к чему, если изначально всё разбить на слова. Т.е. в чём оптимизация, если выделяется больше памяти, больше операций и прямые индексы? Сперва, на мой взгляд надо подготовить строки, т.е. в нашем случае можно всё загнать просто в двумерный массив строк, и все операции производить в нём, с отдельными словами.

Ответ 3



private void GetUnion(List lst1, List lst2) { // List для результата List lstUnion = new List(); foreach (string value in lst1) { string valueColumn1 = value.Split(';')[0]; string valueColumn2 = value.Split(';')[1]; string valueColumn3 = value.Split(';')[2]; // Ищем совпадения, есть ли valueColumn2 и valueColumn3 в lst2 во 2-й и 3-й колонке, // С 1-й и 2-й не перепутаем, // ";russia;japan" - такая последовательность со знаком ';' в начале // может быть только если текст начинается со второй колонки. string result = lst2.FirstOrDefault(s => s.Contains(";" + valueColumn2 + ";" + valueColumn3)); if (result != null) // если совпадения есть { if (!lstUnion.Contains(result)) // и если значение уже не добавлено { lstUnion.Add(result); MessageBox.Show(result); // для проверки } } } // В итоге в lstUnion одно значение - "spain;russia;japan" }

Ответ 4



Открываешь .csv как двумерный массив данных с помощью: Как просто работать с / открыть / изменить / сохранить Excel / CSV файлы Сравниваешь сначала по количеству ячеек в массивах, а потом если оно одинаковое, то по нутрянке ячеек двумя foreach (один во втором). :)

четверг, 28 ноября 2019 г.

Как просто работать с / открыть / изменить / сохранить Excel - xlsx / CSV файлы

#c_sharp #excel #csv


Сколько я ни искал, всё как-то уж больно сложно и избыточно функционально...

А я хотел максимальной простоты — работать с таблицей как с двумерным массивом строк.

Ответ к которому я пришел -  внизу :)



Полная поддержка CSV должна в себя включать:


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

    


Ответы

Ответ 1



EXCEL: Здесь я написал очень простую библиотеку на основе ClosedXML для того, чтобы не задумываясь иметь возможность работать с таблицами MS Excel как с двумерным массивом: что может быть легче в использовании? Пример конечного кода для работы с моим классом: Excel xl = new Excel(); //создаем инстанс xl.FileOpen("c:\\file1.xlsx"); //открываем файл var row1Cell6Value = xl.Rows[0][5]; //вытягиваем значение из 1 строки 6й ячейки xl.AddRow("asdf","asdffffff","5"); //добавляем еще одну строку с 3мя ячейками xl.FileSave("c:\\file2.xlsx"); //сохраняем файл Фактически, это и есть все методы — аскетский минимализм :) Если нужно написать формулу, можно использовать следующий код: var widthAdress = Excel.GetExcelPos(0, 1); var heightAdress = Excel.GetExcelPos(0, 2); xl.Rows[0][0] = String.Format("={0}*{1}", widthAdress , heightAdress); CSV: И абсолютно с тем же подходом аскетизма есть не менее простая либа для работы с CSV файлами как с двумерным массивом данных. Csv csv = new Csv(); //создаем инстанс читалки csv.FileOpen("c:\\file1.csv"); //открываем файл var row1Cell6Value = csv.Rows[0][5]; //читаем 6ю ячейку 1й строки csv.AddRow("asdf","asdffffff","5"); // добавляем строку из 3х ячеек csv.FileSave("c:\\file2.csv"); // сохраняем файл Актуальный код обоих классов вы найдете здесь: https://github.com/ukushu/DataExporter Теперь немного отступим что бы рассказать почему мой код написан именно так, а не иначе Этот блок будет полезен тем, кому будет мало моей либы, и кто хочет больше возможностей в работе с Microsoft Excel. Сначала я пытался работать с Excel-файлами при помощи Microsoft.Office.Interop.Excel, который по факту: Медленный (я сейвил таблицу всего лишь в 11 250 ячеек на протяжении 22 секунд!!!). У него много утечек памяти (ни в коем случае не используйте эту библиотеку для веб-сайтов или приложений, где на сервере генерируются файлы Office-форматов: у вас кончится оперативная память довольно быстро и сайт или приложение упадёт). Требует наличия MS Office определённой версии. На каждую машину, где будет работать ваше приложение. Неудобный в использовании. Имеет множество подводных камней из-за которых лишние Excel'евские сервисы будут оставаться запущенными... Считаю очень неудачным решением через него взаимодействовать. Потом я пытался работать через OleDB. Этот путь привел меня в никуда просто по той причине, что там невозможно работать с формулами. Считать формулу ты не можешь — только записать. В целом этот путь явно лучше, быстрее и приятнее, но отсутствие возможности править формулы меня очень огорчало. И так я пришел к OpenXML. Как следствие — тоже относительно печальный опыт. Работать с ним просто-напросто неудобно. Не знаю, чем авторы думали. И я пришел к конечному решению — обертки вокруг OpenXML - ClosedXML. Это решение уже позволило написать: Удобный и легко читаемый код либы. При этом достаточно быстрый код. (сейв файла на 20 000 ячеек обходится в 00:00:00.6787608, что быстрее более чем в 57 раз чем путь Interop). А также не требует установленного MS Excel. :) Важные минуса: нужно уточнить что работает только с ".xlsx" файлами! Но не с ".xls"! Решение для работы с Excel требует подтягивание целых 2х библиотек (OpenXML, ClosedXML) решение для работы с CSV не будет работать, например, на Unity. Это из-за того, что пришось использовать библиотеку с VB.