Size: a a a

Python для анализа данных

2020 December 23

AD

Andrew Dakhnovsky in Python для анализа данных
Vlad Nykytenko
можете передать в качестве значения ключа список значений, например так {'c': [’03',  '30’]}
и будет список из трех словаре вида
[{'a': '01', 'b': '02'}, {'a': '10', 'b': '20'}, {'c': ['03', '30']}]
кому там шо помогло - решительно непонятно
источник

ND

Natalya Davydova in Python для анализа данных
Показывай, что помогло) Тоже непонятно
источник

АМ

Алексей Макаров... in Python для анализа данных
Борис Евдеев
Всем привет. Помогите, пожалуйста, как расширить список.

Есть список:
ds = [{'a': '01', 'b': '02'}, {'a': '10', 'b': '20'}]

Добавляю значения:
ds.append({'c': '03', 'c': '30'})

Ожидаю увидеть:
[{'a': '01', 'b': '02', 'c': '03'}, {'a': '10', 'b': '20', 'c': '30'}]

А вижу:
[{'a': '01', 'b': '02'}, {'a': '10', 'b': '20'}, {'c': '30'}]


Как получить ожидаемое?
Вам нужно пройтись по списку и объединить два словаря вместе:

def merge_two_dicts(x, y):
   z = x.copy()
   z.update(y)
   return z

ds = [{'a': '01', 'b': '02'}, {'a': '10', 'b': '20'}]

d = [{'c': '03'}, {'c': '30'}]

ds_2 = [merge_two_dicts(x,y) for x,y in zip(ds,d)]
источник

АМ

Алексей Макаров... in Python для анализа данных
Борис Евдеев
Всем привет. Помогите, пожалуйста, как расширить список.

Есть список:
ds = [{'a': '01', 'b': '02'}, {'a': '10', 'b': '20'}]

Добавляю значения:
ds.append({'c': '03', 'c': '30'})

Ожидаю увидеть:
[{'a': '01', 'b': '02', 'c': '03'}, {'a': '10', 'b': '20', 'c': '30'}]

А вижу:
[{'a': '01', 'b': '02'}, {'a': '10', 'b': '20'}, {'c': '30'}]


Как получить ожидаемое?
{'c': '03', 'c': '30'} — такую структуру данных делать нельзя, потому что у вас в одном и том же словаре получается два одинаковых ключа 'c'
источник

АМ

Алексей Макаров... in Python для анализа данных
Алексей Макаров
{'c': '03', 'c': '30'} — такую структуру данных делать нельзя, потому что у вас в одном и том же словаре получается два одинаковых ключа 'c'
Вот почему
источник

БЕ

Борис Евдеев... in Python для анализа данных
Natalya Davydova
Показывай, что помогло) Тоже непонятно
Я покажу на итоговом коде, который сделал. Может кому-то пригодится.

Задача: хочу найти все станции метро от которых до м.Кутузовская < 30 минут. Решил сначала парсить все станции, потом время от всех станций до м.Кутузовская, а потом фильтровать в Pandas. Для этого нашёл более менее адекватный сайт (в отличии от яндекс.метро и mosmetro), где есть информация, которая не спрятана в самое не хочу... :)

Решение того, что спрашивал написано в последнем цикле for

```
import requests
from bs4 import BeautifulSoup as bs
import re
import pandas as pd

dataset = []
headers = {'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'}

# ID станции от которой ищем время
from_station = 239

url = 'https://metrobook.ru/'
webpage = requests.get(url, headers)
response = BeautifulSoup(webpage.content, 'html.parser')
main__div = response.find_all('div', class_='stName')

for data in main__div:
   station_id = data.find('span', class_='stName').get('mb_sd_id')
   station = data.find('span', class_='stName').get_text()
   station = re.search("[^(\n|\r)]+", station).group()
   station = station.replace("\xa0"," ").strip()
   dataset.append({
       "id": station_id,
       "stName": station})

for row in range(len(dataset)):
   settings = {'mod': 'metrobook', 'oper': 'getShortestPath','sdid1': from_station, 'sdid2': dataset[row]['id'],'mid': '2','whatToMinimize': '0'}
   table = requests.post('https://metrobook.ru/kcmsajax.php', data=settings, headers=headers).json()
   dataset[row]['changeTime'] = table['table']['changeTime']
   dataset[row]['changeNumber'] = table['table']['changeNumber']
   dataset[row]['transitTime'] = table['table']['transitTime']
   dataset[row]['ans'] = table['table']['ans']
   dataset[row]['ans_count'] = len(table['table']['ans'])
   dataset[row]['totalTime'] = table['table']['totalTime']

df = pd.DataFrame(dataset)
df.changeTime = df.changeTime / 60
df.totalTime = df.totalTime / 60
df.transitTime = df.transitTime / 60
df[(df.totalTime < 30) & (df.changeNumber <= 2)]
```
источник

БЕ

Борис Евдеев... in Python для анализа данных
Борис Евдеев
Я покажу на итоговом коде, который сделал. Может кому-то пригодится.

Задача: хочу найти все станции метро от которых до м.Кутузовская < 30 минут. Решил сначала парсить все станции, потом время от всех станций до м.Кутузовская, а потом фильтровать в Pandas. Для этого нашёл более менее адекватный сайт (в отличии от яндекс.метро и mosmetro), где есть информация, которая не спрятана в самое не хочу... :)

Решение того, что спрашивал написано в последнем цикле for

```
import requests
from bs4 import BeautifulSoup as bs
import re
import pandas as pd

dataset = []
headers = {'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'}

# ID станции от которой ищем время
from_station = 239

url = 'https://metrobook.ru/'
webpage = requests.get(url, headers)
response = BeautifulSoup(webpage.content, 'html.parser')
main__div = response.find_all('div', class_='stName')

for data in main__div:
   station_id = data.find('span', class_='stName').get('mb_sd_id')
   station = data.find('span', class_='stName').get_text()
   station = re.search("[^(\n|\r)]+", station).group()
   station = station.replace("\xa0"," ").strip()
   dataset.append({
       "id": station_id,
       "stName": station})

for row in range(len(dataset)):
   settings = {'mod': 'metrobook', 'oper': 'getShortestPath','sdid1': from_station, 'sdid2': dataset[row]['id'],'mid': '2','whatToMinimize': '0'}
   table = requests.post('https://metrobook.ru/kcmsajax.php', data=settings, headers=headers).json()
   dataset[row]['changeTime'] = table['table']['changeTime']
   dataset[row]['changeNumber'] = table['table']['changeNumber']
   dataset[row]['transitTime'] = table['table']['transitTime']
   dataset[row]['ans'] = table['table']['ans']
   dataset[row]['ans_count'] = len(table['table']['ans'])
   dataset[row]['totalTime'] = table['table']['totalTime']

df = pd.DataFrame(dataset)
df.changeTime = df.changeTime / 60
df.totalTime = df.totalTime / 60
df.transitTime = df.transitTime / 60
df[(df.totalTime < 30) & (df.changeNumber <= 2)]
```
Логика:
1. С сайта спарсил название и ID станций, добавил в список со словарями.
2. Отправил по каждой ID станции POST запрос и получил JSON
3. Добавил данные из JSON в словарь
4. Отфильтровал
источник

АМ

Алексей Макаров... in Python для анализа данных
Борис Евдеев
Я покажу на итоговом коде, который сделал. Может кому-то пригодится.

Задача: хочу найти все станции метро от которых до м.Кутузовская < 30 минут. Решил сначала парсить все станции, потом время от всех станций до м.Кутузовская, а потом фильтровать в Pandas. Для этого нашёл более менее адекватный сайт (в отличии от яндекс.метро и mosmetro), где есть информация, которая не спрятана в самое не хочу... :)

Решение того, что спрашивал написано в последнем цикле for

```
import requests
from bs4 import BeautifulSoup as bs
import re
import pandas as pd

dataset = []
headers = {'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'}

# ID станции от которой ищем время
from_station = 239

url = 'https://metrobook.ru/'
webpage = requests.get(url, headers)
response = BeautifulSoup(webpage.content, 'html.parser')
main__div = response.find_all('div', class_='stName')

for data in main__div:
   station_id = data.find('span', class_='stName').get('mb_sd_id')
   station = data.find('span', class_='stName').get_text()
   station = re.search("[^(\n|\r)]+", station).group()
   station = station.replace("\xa0"," ").strip()
   dataset.append({
       "id": station_id,
       "stName": station})

for row in range(len(dataset)):
   settings = {'mod': 'metrobook', 'oper': 'getShortestPath','sdid1': from_station, 'sdid2': dataset[row]['id'],'mid': '2','whatToMinimize': '0'}
   table = requests.post('https://metrobook.ru/kcmsajax.php', data=settings, headers=headers).json()
   dataset[row]['changeTime'] = table['table']['changeTime']
   dataset[row]['changeNumber'] = table['table']['changeNumber']
   dataset[row]['transitTime'] = table['table']['transitTime']
   dataset[row]['ans'] = table['table']['ans']
   dataset[row]['ans_count'] = len(table['table']['ans'])
   dataset[row]['totalTime'] = table['table']['totalTime']

df = pd.DataFrame(dataset)
df.changeTime = df.changeTime / 60
df.totalTime = df.totalTime / 60
df.transitTime = df.transitTime / 60
df[(df.totalTime < 30) & (df.changeNumber <= 2)]
```
Интересный получился скрипт👍🏻
источник

БЕ

Борис Евдеев... in Python для анализа данных
Алексей Макаров
Интересный получился скрипт👍🏻
Спасибо :)
Возможно многое можно сделать проще и короче, а в идеале засунуть в функции. Но я только учусь :)
источник
2020 December 24

AD

Andrew Dakhnovsky in Python для анализа данных
Борис Евдеев
Спасибо :)
Возможно многое можно сделать проще и короче, а в идеале засунуть в функции. Но я только учусь :)
ну хз, может тут так принято, но в более других местах за такие  портянки кода пиздят ногами  сбрасывают в тартар
ну в смысле или заливай на:
https://pastebin.com
https://dpaste.org/
http://controlc.com/
или хотя бы оформляй как код
т.е. вначале три символа ``` - на букве ё в латинской раскладке и в конце
типа тегов
или выделяй правой кнопкой и
источник

БЕ

Борис Евдеев... in Python для анализа данных
Andrew Dakhnovsky
ну хз, может тут так принято, но в более других местах за такие  портянки кода пиздят ногами  сбрасывают в тартар
ну в смысле или заливай на:
https://pastebin.com
https://dpaste.org/
http://controlc.com/
или хотя бы оформляй как код
т.е. вначале три символа ``` - на букве ё в латинской раскладке и в конце
типа тегов
или выделяй правой кнопкой и
Андрей, извиняюсь, что получилась портянка. Первый раз написал вопрос в группу. Спасибо за советы :)
источник

AD

Andrew Dakhnovsky in Python для анализа данных
Борис Евдеев
Андрей, извиняюсь, что получилась портянка. Первый раз написал вопрос в группу. Спасибо за советы :)
да ниче все ок
однострочники (или внутри строки) код можно выделять по одному символу ` в начале и в конце
источник

AD

Andrew Dakhnovsky in Python для анализа данных
Борис Евдеев
Я покажу на итоговом коде, который сделал. Может кому-то пригодится.

Задача: хочу найти все станции метро от которых до м.Кутузовская < 30 минут. Решил сначала парсить все станции, потом время от всех станций до м.Кутузовская, а потом фильтровать в Pandas. Для этого нашёл более менее адекватный сайт (в отличии от яндекс.метро и mosmetro), где есть информация, которая не спрятана в самое не хочу... :)

Решение того, что спрашивал написано в последнем цикле for

```
import requests
from bs4 import BeautifulSoup as bs
import re
import pandas as pd

dataset = []
headers = {'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9','user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36'}

# ID станции от которой ищем время
from_station = 239

url = 'https://metrobook.ru/'
webpage = requests.get(url, headers)
response = BeautifulSoup(webpage.content, 'html.parser')
main__div = response.find_all('div', class_='stName')

for data in main__div:
   station_id = data.find('span', class_='stName').get('mb_sd_id')
   station = data.find('span', class_='stName').get_text()
   station = re.search("[^(\n|\r)]+", station).group()
   station = station.replace("\xa0"," ").strip()
   dataset.append({
       "id": station_id,
       "stName": station})

for row in range(len(dataset)):
   settings = {'mod': 'metrobook', 'oper': 'getShortestPath','sdid1': from_station, 'sdid2': dataset[row]['id'],'mid': '2','whatToMinimize': '0'}
   table = requests.post('https://metrobook.ru/kcmsajax.php', data=settings, headers=headers).json()
   dataset[row]['changeTime'] = table['table']['changeTime']
   dataset[row]['changeNumber'] = table['table']['changeNumber']
   dataset[row]['transitTime'] = table['table']['transitTime']
   dataset[row]['ans'] = table['table']['ans']
   dataset[row]['ans_count'] = len(table['table']['ans'])
   dataset[row]['totalTime'] = table['table']['totalTime']

df = pd.DataFrame(dataset)
df.changeTime = df.changeTime / 60
df.totalTime = df.totalTime / 60
df.transitTime = df.transitTime / 60
df[(df.totalTime < 30) & (df.changeNumber <= 2)]
```
о!
другое дело!
источник

БЕ

Борис Евдеев... in Python для анализа данных
Andrew Dakhnovsky
о!
другое дело!
Исправился :)
источник

АМ

Алексей Макаров... in Python для анализа данных
Борис Евдеев
Исправился :)
Красота!)
источник

СИ

Сергей Ильин... in Python для анализа данных
Andrew Dakhnovsky
ну хз, может тут так принято, но в более других местах за такие  портянки кода пиздят ногами  сбрасывают в тартар
ну в смысле или заливай на:
https://pastebin.com
https://dpaste.org/
http://controlc.com/
или хотя бы оформляй как код
т.е. вначале три символа ``` - на букве ё в латинской раскладке и в конце
типа тегов
или выделяй правой кнопкой и
+
источник

СИ

Сергей Ильин... in Python для анализа данных
dataset[row]['changeTime'] = table['table']['changeTime']
dataset[row]['changeNumber'] = table['table']['changeNumber']
dataset[row]['transitTime'] = table['table']['transitTime']
dataset[row]['ans'] = table['table']['ans']
dataset[row]['ans_count'] = len(table['table']['ans'])
dataset[row]['totalTime'] = table['table']['totalTime']


эмм. может, я чего-то не вижу.
но вопрос все равно задам.
cкажите, а для чего вы это делаете?
в table вы ведь уже положили json?
(судя по
table = requests.post('https://metrobook.ru/kcmsajax.php', data=settings, headers=headers).json() - положили)
и в dataset вы каждый раз добавляете колонку со значением из json?
я о том, для чего вы это делаете “по шагам”?
почему бы не вытащить все это каким-нибудь read_json ?

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_json.html
источник

БЕ

Борис Евдеев... in Python для анализа данных
Сергей Ильин
dataset[row]['changeTime'] = table['table']['changeTime']
dataset[row]['changeNumber'] = table['table']['changeNumber']
dataset[row]['transitTime'] = table['table']['transitTime']
dataset[row]['ans'] = table['table']['ans']
dataset[row]['ans_count'] = len(table['table']['ans'])
dataset[row]['totalTime'] = table['table']['totalTime']


эмм. может, я чего-то не вижу.
но вопрос все равно задам.
cкажите, а для чего вы это делаете?
в table вы ведь уже положили json?
(судя по
table = requests.post('https://metrobook.ru/kcmsajax.php', data=settings, headers=headers).json() - положили)
и в dataset вы каждый раз добавляете колонку со значением из json?
я о том, для чего вы это делаете “по шагам”?
почему бы не вытащить все это каким-нибудь read_json ?

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_json.html
В первой части кода список со словарями:
ds = dataset[:2]
print
(ds)
Out:
[{'id': '66', 'stName': 'Новослободская'},
{'id': '67', 'stName': 'Менделеевская'}]

Поcле перебора id в POST-запросах получил JSON (изменил код для наглядности)
ds2 = []
for row in range(len(ds)):
   settings = {'mod': 'metrobook', 'oper': 'getShortestPath',
               'sdid1': from_station, 'sdid2': ds[row]['id'],
               'mid': '2','whatToMinimize': '0'}
   table = requests.post('https://metrobook.ru/kcmsajax.php', data=settings, headers=headers).json()
   ds2.append(table['table'])

JSON с ответом по ID выглядит так:
print(table)
Out:
{'success': True,
'totalCount': 0,
'table': {'changeTime': 120,
 'changeNumber': 1,
 'transitTime': 1140,
 'ans': [239, 238, 132, 206, 88, 101, 226, 225, 67],
 'totalTime': 1260},
'errors': []}

Отсюда нужен только словарь table:
print(table['table'])
Out:
{'changeTime': 120,
'changeNumber': 1,
'transitTime': 1140,
'ans': [239, 238, 132, 206, 88, 101, 226, 225, 67],
'totalTime': 1260}

В цикле выше я добавил словарь table в отдельный список:
print(ds2)
Out:
[{'changeTime': 240,
 'changeNumber': 1,
 'transitTime': 1140,
 'ans': [239, 238, 132, 206, 88, 86, 89, 91, 66],
 'totalTime': 1380},
{'changeTime': 120,
 'changeNumber': 1,
 'transitTime': 1140,
 'ans': [239, 238, 132, 206, 88, 101, 226, 225, 67],
 'totalTime': 1260}]

Теперь нужно расширить словари в ds словарями из ds2. Это я и спрашивал выше , как объединить, т.к. не сообразил самостоятельно и сделал именно добавлением "по шагам".

Если использовать для этого pandas, наверное бы сделал по-другому. Сначала в ds2 добавил бы id по которому отправляю POST запрос, а потом:

df = pd.DataFrame(ds)
df2 = pd.DataFrame(ds2)
df3 = pd.merge(left=df, right=df2, on="id")
источник

СИ

Сергей Ильин... in Python для анализа данных
Борис Евдеев
В первой части кода список со словарями:
ds = dataset[:2]
print
(ds)
Out:
[{'id': '66', 'stName': 'Новослободская'},
{'id': '67', 'stName': 'Менделеевская'}]

Поcле перебора id в POST-запросах получил JSON (изменил код для наглядности)
ds2 = []
for row in range(len(ds)):
   settings = {'mod': 'metrobook', 'oper': 'getShortestPath',
               'sdid1': from_station, 'sdid2': ds[row]['id'],
               'mid': '2','whatToMinimize': '0'}
   table = requests.post('https://metrobook.ru/kcmsajax.php', data=settings, headers=headers).json()
   ds2.append(table['table'])

JSON с ответом по ID выглядит так:
print(table)
Out:
{'success': True,
'totalCount': 0,
'table': {'changeTime': 120,
 'changeNumber': 1,
 'transitTime': 1140,
 'ans': [239, 238, 132, 206, 88, 101, 226, 225, 67],
 'totalTime': 1260},
'errors': []}

Отсюда нужен только словарь table:
print(table['table'])
Out:
{'changeTime': 120,
'changeNumber': 1,
'transitTime': 1140,
'ans': [239, 238, 132, 206, 88, 101, 226, 225, 67],
'totalTime': 1260}

В цикле выше я добавил словарь table в отдельный список:
print(ds2)
Out:
[{'changeTime': 240,
 'changeNumber': 1,
 'transitTime': 1140,
 'ans': [239, 238, 132, 206, 88, 86, 89, 91, 66],
 'totalTime': 1380},
{'changeTime': 120,
 'changeNumber': 1,
 'transitTime': 1140,
 'ans': [239, 238, 132, 206, 88, 101, 226, 225, 67],
 'totalTime': 1260}]

Теперь нужно расширить словари в ds словарями из ds2. Это я и спрашивал выше , как объединить, т.к. не сообразил самостоятельно и сделал именно добавлением "по шагам".

Если использовать для этого pandas, наверное бы сделал по-другому. Сначала в ds2 добавил бы id по которому отправляю POST запрос, а потом:

df = pd.DataFrame(ds)
df2 = pd.DataFrame(ds2)
df3 = pd.merge(left=df, right=df2, on="id")
с тем, что в выводе - более-менее понятно.
не понятно было именно почему “по шагам”.
источник

БЕ

Борис Евдеев... in Python для анализа данных
Сергей Ильин
с тем, что в выводе - более-менее понятно.
не понятно было именно почему “по шагам”.
Не сообразил, как расширить словари внутри списка кратко, что-то вроде:
ds.append(ds2)

Поэтому добавил все атрибуты отдельно. Если есть решение без пандаса - буду рад :)
источник