I'm trying to use the following geojson for UK local authorities, but it displays a blank map.
<https://martinjc.github.io/UK-GeoJSON/json/eng/topo_lad.json -O UK_counties.json>
My table lists most of the local authorities in the same way. Not sure if its the key_on reference that's the only problem or if there's more to it.
My code so far is below:
threshold_scale = np.linspace(df_ctbl['Population'].min(), df_ctbl['Population'].max(), 6, dtype=int)
threshold_scale = threshold_scale.tolist() # change the numpy array to a list
threshold_scale[-1] = threshold_scale[-1] + 1 # make sure that the last value of the list is greater than the maximum immigration
# let Folium determine the scale.
londonf_map = folium.Map(location=[latitudeld, longitudeld], zoom_start=4, tiles='Mapbox Bright')
londonf_map.choropleth(
geo_data=uk_geo,
data=df_ctbl,
columns=['Local Authorityp', 'Population'],
key_on= 'properties.lad13nm',
threshold_scale=threshold_scale,
fill_color='YlOrRd',
fill_opacity=0.7,
line_opacity=0.2,
legend_name='UK Population in 2019',
reset=True
)
londonf_map
Can anyone help? Thanks
You can have a look at this answer : question about Mapbox bright. I think you have a problem with the tiles name "Mapbox Bright".
Related
I am working with the polyline of google, I would like to give a set of coordinates and generate the correct polyline and viceversa. In particular in the end i would like to url encode the result (the polyline).
When I insert a polyline like:
code = '%28%28akntGkozv%40kcCka%40us%40y%7BDfvAm%7BBnuCj_Aus%40fzG%29%29'
I use the polyline package: https://pypi.org/project/polyline/, and first I decode the polyline in order to see the coordinates:
coordinates = polyline.decode(code)
print(coordinates)
>> [(3e-05, -0.0001), (-0.0001, -7e-05), (-0.0002, -0.0002), (45.46221, 35.36626), (45.4621, 35.36617), (45.48328, 35.39727), (45.48317, 35.39718), (45.5172, 35.39707), (45.51711, 35.39816), (45.51723, 35.39814), (45.5172, 35.38418), (45.51823, 35.3843), (45.51821, 35.38428), (45.49413, 35.37398), (45.52816, 35.37387), (45.52807, 35.32855), (45.5281, 35.32845), (45.52823, 35.32848), (45.52813, 35.32861)]
and everything here is fine, the problems comes when I try to encode the coordinates back to the polyline (which is my ultimate goal since in the end i would like to give some coordinates and obtain the corresponding polyline)
new_code = polyline.encode(coordinates)
print(new_code)
>> ERXERXakntGkozvETPkcCkaETPusETPyEWBDfvAmEWBBnuCj_AusETPfzGERYERY
Which is slightly different from the original and if put back in the url it doesnt work!
So my question here are:
what kind of encoding is new_code? I have tried to encode it in percentage url using urllib.parse.quote(new_code) but the result is exactly the same, maybe I neeed to specify some particular encoding style but i didnt found anything.
The polyline that I used is a square inside the city of Milan (so only 4 points, maximum 5, are required to identify this area), but the coordinates results from the polyline.decode gives me back a list with 19 points with coordinates that are not even close to the city of Milan. Why?
Ok so basically all of my problems came from the fact that the string i was considering: %28%28akntGkozv%40kcCka%40us%40y%7BDfvAm%7BBnuCj_Aus%40fzG%29%29
contains %28%28 and %29%29 which are not part of the polyline but are simply two (( and )) inserted by the particular url of the site I was using. A simple replace and an encode return the correct polyline:
code = '%28%28akntGkozv%40kcCka%40us%40y%7BDfvAm%7BBnuCj_Aus%40fzG%29%29'
code = code.replace('%28', '').replace('%29', '')
code = urllib.parse.unquote(code)
print(code)
>> irotG_hzv#woBmE}i#yjE`oBwkDf|ChRhMzeG}~BxcB
Which infact, if put inside the polyline.decode returns exactly the coordinates that I have used:
coordinates = polyline.decode(code)
print(coordinates)
>> [(45.46869, 9.15088), (45.48673, 9.15191), (45.4936, 9.18452), (45.47567, 9.21216), (45.45051, 9.20907), (45.44822, 9.16701), (45.46869, 9.15088)]
Which are exactly 7 (now i have changed the shape so a sixtagon instead of a square) and points exactly in the city of Milan
I'm using coordinate_cleaner's country test cc_coun but it's flagging entries with coordinates near to the edges country borders. To try to keep them I wanted to buffer the terrestrial area of countries, essentially expanding their borders a little so that it doesn't flag these entries.
I've tried:
require(rnaturalearth)
world <- ne_countries(scale = "large", returnclass = "sf") %>% st_buffer(dist=.001)
Using st_buffer(dist=.001) does change the geometry, but I noticed whatever I put into dist doesn't matter as it changes it to the same thing regardless (I tried .001, 0.1, 1, 2, and -1, though any minus number removes the geometry altogether).
I found that maybe I need to transform my sf file into something else and then use st_buffer so it's in meters rather than degrees(?). I saw this question/answer but I don't understand it well enough to help my situation: What unit is the `dist` argument in `st_buffer` set to by default?
In the end I'm looking to create a SpatialPolygonsDataFrame reference file to feed into cc_coun. Using the above code I followed on with:
world <- sf:::as_Spatial(world)
coun_test <- cc_coun(x = data,
lon = "Decimal_Long",
lat = "Decimal_Lat",
iso3 = "Country_code",
value = "flagged",
ref = world,
verbose = TRUE)
Which ended up flagging more entries than when I didn't use st_buffer on the reference fine.
In summary, I want to add a buffer to the edge of every country border by around 100 meters in a file I can use as a reference in this test. Is this the best way to go about it or is there a better/easier way? I'd appreciate any advice.
Thank you
I am trying to rotate Revit elements about their center points. In order to do that, I need to select a Revit element and find its center point, then create a line with the coordinates at that elements center point.
My best idea to accomplish this is to wrap a Revit element in a bounding box and then find the center of that box. My problem is that I am unsure how to accomplish this.
I am using pyRevit (amazing tool) and I am stuck on how to either wrap the selected element with a bounding box or retrieve its existing bounding box.
Any help would be greatly appreciated! I am really trying to learn the Revit API and understand how everything works. I am making progress but there is a lot to unpack.
def pickobject():
from Autodesk.Revit.UI.Selection import ObjectType
#define the active Revit application and document
app = __revit__.Application
doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument
#define a transaction variable and describe the transaction
t = Transaction(doc, 'This is my new transaction')
# Begin new transaction
t.Start()
# Select an element in Revit
picked = uidoc.Selection.PickObject(ObjectType.Element, "Select something.")
### ?????????? ###
# Get bounding box of selected element.
picked_bb = BoundingBoxXYZ(picked)
# Get max and min points of bounding box.
picked_bb_max = picked_bb.Max
picked_bb_min = picked_bb.Min
# Get center point between max and min points of bounding box.
picked_bb_center = (picked_bb_max + picked_bb_min) / 2
### ?????????? ###
# Close the transaction
t.Commit()
return picked, picked_bb_center
Thanks in advance for taking a look at what I have so far. Please let me know if anything needs further clarification!
edit:
#CyrilWaechter
I think you are right. Using LocationPoint would probably make more sense. I looked through the script you linked (thank you btw!) and I tried implementing this section in my code.
transform = doc.GetElement(picked.ElementId).GetTransform()
I am passing the ElementId through this statement but I get the error, "Wall" object has no attribute 'GetTransform'. Could you please help me understand this?
edit 2:
Thanks #JeremyTammik and #CyrilWaechter, your insights helped me understand where I was going wrong. While I still feel that certain properties are ambiguous in the Revit API, I was able to get my code to execute properly. I will post the code that I was able to get working below.
The centre of the bounding box is very easy to obtain. picked is a Reference. Get the ElementId from that, open it using doc.GetElement, and retrieve the bounding box using get_BoundingBox, cf. Conduits Intersecting a Junction Box
:
Element e = Util.SelectSingleElement(
uidoc, "a junction box" );
BoundingBoxXYZ bb = e.get_BoundingBox( null );
For certain elements and certain irregular shapes, you might want to use the centroid instead of the bounding box:
Solid Centroid and Volume Calculation
GetCentroid on GitHub
Edited and preserved for posterity by The Building Coder:
Python Rotate Picked Around Bounding Box Centre
Many thanks to Christian for the interesting discussion and Cyril for the wealth of additional information he provides!
Here is how I was able to solve my problem using pyRevit. This code allows you to rotate an element about its Z axis from the center of its bounding box.
To use this code, select a single Revit element and then open the Revit Python Shell. Copy and paste the code below into the Revit Python Shell notepad and click the run button. This will rotate the element by 45 degrees because the current rotateSelectedElement() argument is 45. You may change this number to any value before running.
# Import the math module to convert user input degrees to radians.
import math
# Get a list of all user selected objects in the Revit Document.
selection = [doc.GetElement(x) for x in uidoc.Selection.GetElementIds()]
# Definitions
def rotateSelectedElement(degrees_to_rotate):
from Autodesk.Revit.UI.Selection import ObjectType
#define the active Revit application and document
app = __revit__.Application
doc = __revit__.ActiveUIDocument.Document
uidoc = __revit__.ActiveUIDocument
#define a transaction variable and describe the transaction
t = Transaction(doc, 'This is my new transaction')
# Convert the user input from degrees to radians.
converted_value = float(degrees_to_rotate) * (math.pi / 180.0)
# Begin new transaction
t.Start()
# Get the first selected element from the current Revit doc.
el = selection[0].Id
# Get the element from the selected element reference
el_ID = doc.GetElement(el)
# Get the Bounding Box of the selected element.
el_bb = el_ID.get_BoundingBox(doc.ActiveView)
# Get the min and max values of the elements bounding box.
el_bb_max = el_bb.Max
el_bb_min = el_bb.Min
# Get the center of the selected elements bounding box.
el_bb_center = (el_bb_max + el_bb_min) / 2
#Create a line to use as a vector using the center location of the bounding box.
p1 = XYZ(el_bb_center[0], el_bb_center[1], 0)
p2 = XYZ(el_bb_center[0], el_bb_center[1], 1)
myLine = Line.CreateBound(p1, p2)
# Rotate the selected element.
ElementTransformUtils.RotateElement(doc, el, myLine, converted_value)
# Close the transaction
t.Commit()
# Execute
# Add the desired degrees to rotate by as an argument for rotateSelectedElement()
rotateSelectedElement(45)
edit: Made code clearer. Code now executes in Revit Python Shell without any further modifications. Refer to directions above if you have trouble!
Assume I have an array of Strings:
['Laptop Apple Macbook Air A1465, Core i7, 8Gb, 256Gb SSD, 15"Retina, MacOS' ... 'another device description']
I'd like to extract from this description features like:
item=Laptop
brand=Apple
model=Macbook Air A1465
cpu=Core i7
...
Should I prepare the pre-defined known features first? Like
brands = ['apple', 'dell', 'hp', 'asus', 'acer', 'lenovo']
cpu = ['core i3', 'core i5', 'core i7', 'intel pdc', 'core m', 'intel pentium', 'intel core duo']
I am not sure that I need to use CountVectorizer and TfidfVectorizer here, it's more appropriate to have DictVictorizer, but how can I make dicts with keys extracting values from the entire string?
is it possible with scikit-learn's Feature Extraction? Or should I make my own .fit(), and .transform() methods?
UPDATE:
#sergzach, please review if I understood you right:
data = ['Laptop Apple Macbook..', 'Laptop Dell Latitude...'...]
for d in data:
for brand in brands:
if brand in d:
# ok brand is found
for model in models:
if model in d:
# ok model is found
So creating N-loops per each feature? This might be working, but not sure if it is right and flexible.
Yes, something like the next.
Excuse me, probably you should correct the code below.
import re
data = ['Laptop Apple Macbook..', 'Laptop Dell Latitude...'...]
features = {
'brand': [r'apple', r'dell', r'hp', r'asus', r'acer', r'lenovo'],
'cpu': [r'core\s+i3', r'core\s+i5', r'core\s+i7', r'intel\s+pdc', r'core\s+m', r'intel\s+pentium', r'intel\s+core\s+duo']
# and other features
}
cat_data = [] # your categories which you should convert into numbers
not_found_columns = []
for line in data:
line_cats = {}
for col, features in features.iteritems():
for i, feature in enumerate(features):
found = False
if re.findall(feature, line.lower(), flags=re.UNICODE) != []:
line_cats[col] = i + 1 # found numeric category in column. For ex., for dell it's 2, for acer it's 5.
found = True
break # current category is determined by a first occurence
# cycle has been end but feature had not been found. Make column value as default not existing feature
if not found:
line_cats[col] = 0
not_found_columns.append((col, line))
cat_data.append(line_cats)
# now we have cat_data where each column is corresponding to a categorial (index+1) if a feature had been determined otherwise 0.
Now you have column names with lines (not_found_columns) which was not found. View them, probably you forgot some features.
We can also write strings (instead of numbers) as categories and then use DV. In result the approaches are equivalent.
Scikit Learn's vectorizers will convert an array of strings to an inverted index matrix (2d array, with a column for each found term/word). Each row (1st dimension) in the original array maps to a row in the output matrix. Each cell will hold a count or a weight, depending on which kind of vectorizer you use and its parameters.
I am not sure this is what you need, based on your code. Could you tell where you intend to use this features you are looking for? Do you intend to train a classifier? To what purpose?
I have a pyscript that I am working on and running into issues with the legend.
The goal of the script is to take a csv file with two columns (country, value) that I am joining to a world map based on country name. Once they are joined I turn it into a lyr file and then start to work on the mapping aspects of it.
I want to change the field being mapped to 'value' and then change the mapping to graduated symbols with 5 breaks (at 5,20,50,75,100 % of the max value in the map). The problem being that depending on what layer file is being used the max value changes. I have spent a lot of time searching for how to do this and have still come up short, there are probably some unnecessary bits to my code as well as I am now to python.
How can I get it to map based on graduated symbol based on 5 percent breaks with a changing max value?
Some of the code I have been working on below,
import os, sys, string, arcpy, arcpy.mapping, glob, arcgisscripting,time
from arcpy import env
call blank mxd file, set feature layer, Declare variables
mxd = arcpy.mapping.MapDocument(workspace/blank_4.mxd")
df = arcpy.mapping.ListDataFrames(mxd)[0]
'newname' is the layer file being used
sourceLayer = arcpy.mapping.Layer(newname)
Convert feature classes to layer objects
outLayer = str(newname)
curmap = workspace + filename + ".shp"
arcpy.MakeFeatureLayer_management(curmap, outLayer)
Save layer objects to layer files
LayerFile = str(outLayer) + ".lyr"
arcpy.SaveToLayerFile_management(outLayer, LayerFile)
Define variable for the new layer using LayerFile object
newlayer = arcpy.mapping.Layer(LayerFile)
Adds the new layer to top of TOC in the mxd doc map document
arcpy.mapping.AddLayer(df, newlayer, "TOP")
change the mapping field from country name to fert value
lyr = arcpy.mapping.ListLayers(mxd, newlayer, df)[0]
symbols = arcpy.mapping.Layer(C:\workspace\graduated_symbol2.lyr")
graduated symbols is a blank layer file where I created a legend with 5 breaks (5,20,50,75,100 %) but the range was created based on a max value of 22,000 and now when I run a file with a max value of 35,000 anything above 22,000 becomes blank.
How can I get it to purely work on % breaks, and have the 0/max range of the respective csv file be used??????
Update new layer with sybmology from the source layer
arcpy.ApplySymbologyFromLayer_management(lyr,symbols)
arcpy.mapping.UpdateLayer(df, lyr, symbols, True)
change symbology, colors, and breaks
if lyr.symbologyType == "GRADUATED_COLORS":
lyr.symbology.valueField = "value"
print lyr.symbology.numClasses #
Then I output this to a pdf, but that part is working.
Thanks!