Retain order in select multiple ipywidgets - jupyter-notebook

I have a SelectMultiple IpyWidgets.
import ipywidgets as widgets
d = widgets.SelectMultiple(
options=['Apples', 'Oranges', 'Pears',"Mango"],
#rows=10,
description='Fruits',
disabled=False
)
OP:
print (list(d.value))
['Apples', 'Mango']
Irrespective of the order I select, the order in OP is always the same as in the order the list of options. For example, even if I select Mango first and then Apple the OP is still as given.

You need a workaround to catch the click order, similar as described here:
import ipywidgets as widgets
d = widgets.SelectMultiple(
options=['Apples', 'Oranges', 'Pears',"Mango"],
description='Fruits',
disabled=False
)
foo = []
def on_change(change):
if change['type'] == 'change' and change['name'] == 'value':
for elem in change['new']:
if elem not in foo:
foo.append(elem)
for elem in foo:
if elem not in change['new']:
foo.remove(elem)
d.observe(on_change)
d
foo is just a placeholder. Now if you click 'Mango' and then 'Apple', you get:
print('values:', d.value) # values: ('Apples', 'Mango')
print('click_order:', foo) # click_order: ['Mango', 'Apples']

Related

Put an append list into a bar graph python

I know how to make a bar graph but I'm trying to put a append two append lists inside of the graph
one is the quantity of a item and the other is the item I would like to know if this is possible and if it is how should I do this. This is what I tried.
itemls = [0]
itemquantityls = [0]
option = 0
while option < 3:
Mainmenue = ["Main menue",
"1. ADD AN ITEM",
"2. GENERATE A CHART",
"3. EXIT"]
for i in (Mainmenue):
print(i)
option = int(input("Option you want:"))
if option == 1:
item = (input("add an item:"))
itemquantity = (input("Item quantity:"))
itemls.append(item)
itemquantityls.append(itemquantity)
elif option == 2:
import matplotlib.pyplot as plt
plt.bar(itemls, itemquantityls)
plt.title('Items and quantity')
plt.xlabel('Item')
plt.ylabel('Item quantity')
plt.show()
elif option == 3:
print("program is teminating")
else:
print("Wrong Input try again")
Thanks in advance. :)

Groovy: Dynamically create nested / combine maps in code

I'm trying to dynamically create nested map like below in code.
def people = [
[name: 'Ash', age: '21', gender: 'm'],
[name: 'Jo', age: '22', gender: 'f'],
[name: 'etc.', age: '42', gender: 'f']
]
So I can search it like below
person = people.findAll {item ->
item.gender == 'm' &&
item.age == '21'}
My problem is that whilst I can dynamically create one dimensional maps in code, I don't know how to dynamically combine maps in code to create nested map e.g. let's assume in code I have created two maps name1 and name2. How do I add them to people map so they are nested like above example?
def people = [:]
def name1 = [name:'ash', age:'21', gender:'m']
def name2 = [name:'Jo', age:'22', gender:'f']
I've searched / tried so many posts without success. Below is close, but does not work :(
people.put((),(name1))
people.put((),(name2))
In your example, people is a list of maps, not a nested map
So you can simply do:
def people = []
def name1 = [name:'ash', age:'21', gender:'m']
def name2 = [name:'Jo', age:'22', gender:'f']
Then:
people += name1
people += name2
Or define it in one line:
def people = [name1, name2]

how to iterate over multiple links and scrape everyone of them one by one and save the output in csv using python beautifulsoup and requests

I have this code but don't know how to read the links from a CSV or a list. I want to read the links and scrape details off every single link and then save the data in columns respected to each link into an output CSV.
Here is the code I built to get specific data.
from bs4 import BeautifulSoup
import requests
url = "http://www.ebay.com/itm/282231178856"
r = requests.get(url)
x = BeautifulSoup(r.content, "html.parser")
# print(x.prettify().encode('utf-8'))
# time to find some tags!!
# y = x.find_all("tag")
z = x.find_all("h1", {"itemprop": "name"})
# print z
# for loop done to extracting the title.
for item in z:
try:
print item.text.replace('Details about ', '')
except:
pass
# category extraction done
m = x.find_all("span", {"itemprop": "name"})
# print m
for item in m:
try:
print item.text
except:
pass
# item condition extraction done
n = x.find_all("div", {"itemprop": "itemCondition"})
# print n
for item in n:
try:
print item.text
except:
pass
# sold number extraction done
k = x.find_all("span", {"class": "vi-qtyS vi-bboxrev-dsplblk vi-qty-vert-algn vi-qty-pur-lnk"})
# print k
for item in k:
try:
print item.text
except:
pass
# Watchers extraction done
u = x.find_all("span", {"class": "vi-buybox-watchcount"})
# print u
for item in u:
try:
print item.text
except:
pass
# returns details extraction done
t = x.find_all("span", {"id": "vi-ret-accrd-txt"})
# print t
for item in t:
try:
print item.text
except:
pass
#per hour day view done
a = x.find_all("div", {"class": "vi-notify-new-bg-dBtm"})
# print a
for item in a:
try:
print item.text
except:
pass
#trending at price
b = x.find_all("span", {"class": "mp-prc-red"})
#print b
for item in b:
try:
print item.text
except:
pass
Your question is kind of vague!
Which links are you talking about? There are a hundred on a single ebay page. Which infos would you like to scrape? Similarly there is also a ton.
But anyway, here is I would proceed:
# First, create a list of urls you want to iterate on
urls = []
soup = (re.text, "html.parser")
# Assuming your links of interests are values of "href" attributes within <a> tags
a_tags = soup.find_all("a")
for tag in a_tags:
urls.append(tag["href"])
# Second, start to iterate while storing the info
info_1, info_2 = [], []
for link in urls:
# Do stuff here, maybe its time to define your existing loops as functions?
info_a, info_b = YourFunctionReturningValues(soup)
info_1.append(info_a)
info_2.append(info_b)
Then if you want a nice csv output:
# Don't forget to import the csv module
with open(r"path_to_file.csv", "wb") as my_file:
csv_writer = csv.writer(final_csv, delimiter = ",")
csv_writer.writerows(zip(urls, info_1, info_2, info_3))
Hope this will help?
Of course, don't hesitate to give additional info, so to have additional details
On attributes with BeautifulSoup: https://www.crummy.com/software/BeautifulSoup/bs4/doc/#attributes
About the csv module: https://docs.python.org/2/library/csv.html

Spark: How to translate count(distinct(value)) in Dataframe API's

I'm trying to compare different ways to aggregate my data.
This is my input data with 2 elements (page,visitor):
(PAG1,V1)
(PAG1,V1)
(PAG2,V1)
(PAG2,V2)
(PAG2,V1)
(PAG1,V1)
(PAG1,V2)
(PAG1,V1)
(PAG1,V2)
(PAG1,V1)
(PAG2,V2)
(PAG1,V3)
Working with a SQL command into Spark SQL with this code:
import sqlContext.implicits._
case class Log(page: String, visitor: String)
val logs = data.map(p => Log(p._1,p._2)).toDF()
logs.registerTempTable("logs")
val sqlResult= sqlContext.sql(
"""select page
,count(distinct visitor) as visitor
from logs
group by page
""")
val result = sqlResult.map(x=>(x(0).toString,x(1).toString))
result.foreach(println)
I get this output:
(PAG1,3) // PAG1 has been visited by 3 different visitors
(PAG2,2) // PAG2 has been visited by 2 different visitors
Now, I would like to get the same result using Dataframes and thiers API, but I can't get the same output:
import sqlContext.implicits._
case class Log(page: String, visitor: String)
val logs = data.map(p => Coppia(p._1,p._2)).toDF()
val result = log.select("page","visitor").groupBy("page").count().distinct
result.foreach(println)
In fact, that's what I get as output:
[PAG1,8] // just the simple page count for every page
[PAG2,4]
What you need is the DataFrame aggregation function countDistinct:
import sqlContext.implicits._
import org.apache.spark.sql.functions._
case class Log(page: String, visitor: String)
val logs = data.map(p => Log(p._1,p._2))
.toDF()
val result = logs.select("page","visitor")
.groupBy('page)
.agg('page, countDistinct('visitor))
result.foreach(println)
You can use dataframe's groupBy command twice to do so. Here, df1 is your original input.
val df2 = df1.groupBy($"page",$"visitor").agg(count($"visitor").as("count"))
This command would produce the following result:
page visitor count
---- ------ ----
PAG2 V2 2
PAG1 V3 1
PAG1 V1 5
PAG1 V2 2
PAG2 V1 2
Then use the groupBy command again to get the final result.
df2.groupBy($"page").agg(count($"visitor").as("count"))
Final output:
page count
---- ----
PAG1 3
PAG2 2
I think in the newer versions of Spark it is easier. The following is tested with 2.4.0.
1. First, create an array for sample.
val myArr = Array(
("PAG1","V1"),
("PAG1","V1"),
("PAG2","V1"),
("PAG2","V2"),
("PAG2","V1"),
("PAG1","V1"),
("PAG1","V2"),
("PAG1","V1"),
("PAG1","V2"),
("PAG1","V1"),
("PAG2","V2"),
("PAG1","V3")
)
2. Crate a dataframe
val logs = spark.createDataFrame(myArr)
.withColumnRenamed("_1","page")
.withColumnRenamed("_2","visitor")
3. Now aggregation with distinctCount spark sql function
import org.apache.spark.sql.{functions => F}
logs.groupBy("page").agg(
F.countDistinct("visitor").as("visitor"))
.show()
4. Expected result:
+----+-------+
|page|visitor|
+----+-------+
|PAG1| 3|
|PAG2| 2|
+----+-------+
Use this if you want to display the distinct values of a column
display(sparkDF.select('columnName').distinct())

How to show a QDialog

I need to show a find dialog after pressing Ctrl+F in QWidget, which contains a QTableView. The find dialog will search in the first column of the table to find the matches.
I can show the QMessageBox after pressing Ctrl+F with the following code:
class Widget(QWidget):
def __init__(self,md,parent=None):
QWidget.__init__(self,parent)
layout=QVBoxLayout(self)
# initially construct the visible table
tv = QTableView()
# uncomment this if the last column shall cover the rest
tv.horizontalHeader().setStretchLastSection(True)
tv.show()
# set black grid lines
self.setStyleSheet("gridline-color: rgb(39, 42, 49)")
# construct the Qt model belonging to the visible table
model = NvmQtModel(md)
tv.setModel(model)
tv.resizeRowsToContents()
tv.resizeColumnsToContents()
# set the shortcut ctrl+F for find in menu
shortcut = QShortcut(QKeySequence('Ctrl+f'), self)
shortcut.activated.connect(self.handleFind)
# delegate for decimal
delegate = NvmDelegate()
tv.setItemDelegate(delegate)
self.setGeometry(200,200,600,600) # adjust this later
layout.addWidget(tv)
# set window title
self.setWindowTitle("TITLE")
# find function: search in the first column of the table
def handleFind(self):
reply = QMessageBox.question(
self, 'Find', 'Find Dialog',
QMessageBox.Yes | QMessageBox.No)
if reply == QMessageBox.Yes:
print('Yes')
else:
print('No')
Then I changed the QMessageBox to a QDialog, but now it does not work. I would appreciate if you could tell me where I am not doing it correctly:
class Widget(QWidget):
def __init__(self,md,parent=None):
QWidget.__init__(self,parent)
layout=QVBoxLayout(self)
# initially construct the visible table
tv = QTableView()
# uncomment this if the last column shall cover the rest
tv.horizontalHeader().setStretchLastSection(True)
tv.show()
# set black grid lines
self.setStyleSheet("gridline-color: rgb(39, 42, 49)")
# construct the Qt model belonging to the visible table
model = NvmQtModel(md)
tv.setModel(model)
tv.resizeRowsToContents()
tv.resizeColumnsToContents()
# set the shortcut ctrl+F for find in menu
shortcut = QShortcut(QKeySequence('Ctrl+f'), self)
shortcut.activated.connect(self.handleFind)
# delegate for decimal
delegate = NvmDelegate()
tv.setItemDelegate(delegate)
self.setGeometry(200,200,600,600) # adjust this later
layout.addWidget(tv)
# set window title
self.setWindowTitle("TITLE")
# find function: search in the first column of the table
def handleFind(self):
findDialog = QDialog()
findLabel = QLabel("Find what", findDialog)
findField = QLineEdit(findDialog)
findButton = QPushButton("Find", findDialog)
closeButton = QPushButton("Close", findDialog)
findDialog.show()
If you want the Dialog be a modal Dialog, call findDialog.exec_():
from PyQt4.QtGui import *
def handleFind():
findDialog = QDialog()
#findDialog.setModal(True)
findLabel = QLabel("Find what", findDialog)
findField = QLineEdit(findDialog)
findButton = QPushButton("Find", findDialog)
closeButton = QPushButton("Close", findDialog)
#findDialog.show()
findDialog.exec_()
app = QApplication([])
b = QPushButton("click me")
b.clicked.connect(handleFind)
b.show()
app.exec_()

Resources