I have made a function which produces a map, which I will turn into a gif by plotting 24 versions of the map representing the 24 hours in a day. I can call my map the following way.
get_gif(0.0, '00:00:00', '00.png')
to print the next map I will call the following:
get_gif(1.0, '01:00:00', '01.png')
And so on until up to my final call which will look like this:
get_gif(23.0, '23:00:00', '23.png')
How would I make a loop so that I can make all 24 calls in one go? My first argument is a float between 0.0 to 23.0 (the hours of the day), then a string for the time which I am printing in the map, then another string which is the file name.
For python3.6 and above:
for hour in range(24):
get_gif(float(hour), f"{hour:02}:00:00", f"{hour:02}.png")
What you need is a string formatter. In python that would be something like
'{0}.png'.format(n)
In python the '{0}'.format(n) will replace the {0} with the number n. The variable n can be updated with a for loop. Unfortunately it seems that your file contain things like '01.png' so you cannot do
'{0}.png'.format(1)
Because the name will become 1.png. For this reason you can use an if clause and use
'0{0}.png'.format(n)
If n is smaller then 10.
Related
Hello friends!
Summarization:
I got a ee.FeatureCollection containing around 8500 ee.Point-objects. I would like to calculate the distance of these points to a given coordinate, lets say (0.0, 0.0).
For this i use the function geopy.distance.distance() (ref: https://geopy.readthedocs.io/en/latest/#module-geopy.distance). As input the the function takes 2 coordinates in the form of 2 tuples containing 2 floats.
Problem: When i am trying to convert the coordinates in form of an ee.List to float, i always use the getinfo() function. I know this is a callback and it is very time intensive but i don't know another way to extract them. Long story short: To extract the data as ee.Number it takes less than a second, if i want them as float it takes more than an hour. Is there any trick to fix this?
Code:
fc_containing_points = ee.FeatureCollection('projects/ee-philadamhiwi/assets/Flensburg_100') #ee.FeatureCollection
list_containing_points = fc_containing_points.toList(fc_containing_points.size()) #ee.List
fc_containing_points_length = fc_containing_points.size() #ee.Number
for index in range(fc_containing_points_length.getInfo()): #i need to convert ee.Number to int
point_tmp = list_containing_points.get(i) #ee.ComputedObject
point = ee.Feature(point_tmp) #transform ee.ComputedObject to ee.Feature
coords = point.geometry().coordinates() #ee.List containing 2 ee.Numbers
#when i run the loop with this function without the next part
#i got all the data i want as ee.Number in under 1 sec
coords_as_tuple_of_ints = (coords.getInfo()[1],coords.getInfo()[0]) #tuple containing 2 floats
#when i add this part to the function it takes hours
PS: This is my first question, pls be patient with me.
I would use .map instead of your looping. This stays server side until you export the table (or possibly do a .getInfo on the whole thing)
fc_containing_points = ee.FeatureCollection('projects/eephiladamhiwi/assets/Flensburg_100')
fc_containing_points.map(lambda feature: feature.set("distance_to_point", feature.distance(ee.Feature(ee.Geometry.Point([0.0,0.0])))
# Then export using ee.batch.Export.Table.toXXX or call getInfo
(An alternative might be to useee.Image.paint to convert the target point to an image then, use ee.Image.distance to calculate the distance to the point (as an image), then use reduceRegions over the feature collection with all points but 1) you can only calculate distance to a certain distance and 2) I don't think it would be any faster.)
To comment on your code, you are probably aware loops (especially client side loops) are frowned upon in GEE (primarily for the performance reasons you've run into) but also note that any time you call .getInfo on a server side object it incurs a performance cost. So this line
coords_as_tuple_of_ints = (coords.getInfo()[1],coords.getInfo()[0])
Would take roughly double the time as this
coords_client = coords.getInfo()
coords_as_tuple_of_ints = (coords_client[1],coords_client[0])
Finally, you could always just export your entire feature collection to a shapefile (using ee.batch.Export.Table.... as above) and do all the operations using geopy locally.
I want to print this with a specific width so that they are aligned when printed.
for i in range(len(valuelist)):
print("{0:<5} {0:<5} {0:<5}".format(valuelist[i],averagelist[i],averagesquared[i]))
Somehow, it only shows the valuelist[i] to all 3 columns. The averagelist[i], and averagesquared[i] is not getting shown. All 3 of those will only show valuelist[i].
It works properly when I print them like this.
for i in range(len(valuelist)):
print("{} {} {}".format(valuelist[i],averagelist[i],averagesquared[i]))
It properly works just like how I intended it to be.
I can fix it by putting 2 more prints but I want it to be in a single line.
That is because you are not using the syntax correctly, it should be:
for i in range(len(valuelist)):
print("{0:<5} {1:<5} {2:<5}".format(valuelist[i],averagelist[i],averagesquared[i]))
This is the correct way to format it, as the numbers inside the {} refer to the index of the arguments in the format function. If they are all zero instead like in your code, they will all call on the same argument, which is the first one every time.
I am trying to generate all 16^16,
but there are a few problems. Mainly memory.
I tried to generate them in python like this:
for y in range (0, 16**16):
print '0x%0*X' % (16,y)
This gives me:
OverflowError: range() result has too many items
If I use sys.maxint I get a MemoryError.
To be more precise, I want to generate all combinations of HEX in length of 16, i.e:
0000000000000000
0000000000000001
0000000000000002
...
FFFFFFFFFFFFFFFF
Also, how do I calculate the approximate time it will take me to generate them?
I am open to the use of any programming language as long as I can save them to an output file.
Well... 16^16 = 1.8446744e+19, so lets say you could calculate 10 values per nanosecond (that's a 10GHz rate btw). Then it would take you 16^16 / 10 nanoseconds to compute them all, or 58.4 years. Also, if you could somehow compress each value into 1-bit (which is impossible), it would require 2 exabytes of memory to contain those values (16^16/8/2^60).
This seems like a very artificial exercise. Is it homework, or is there a reason for generating this list? It will be very long (see other answers)!
Having said that, you should ask yourself: why is this happening? The answer is that in Python 2.x, range produces an actual list. If you want to avoid that, you can:
Use Python 3.x, in which range does not actually make a list, but a special generator-like object.
Use xrange, which also doesn't actually make a list, but again produces an object.
As for timing, all of the time will be in writing to the file or screen. You can get an estimate by making a somewhat smaller list and then doing some math, but you have to be careful that it's big enough that the time is dominated by writing the lines, and not opening and closing the file.
But you should also ask yourself how big the resultant file will be... You may not like what you find. Perhaps you mean 2^16?
I am trying to convert from UTC time to LocaleTime in my dataframe. I have a dictionary where I store the number of hours I need to shift for each country code. So for example if I have df['CountryCode'][0]='AU' and I have a df['UTCTime'][0]=2016-08-12 08:01:00 I want to get df['LocaleTime'][0]=2016-08-12 19:01:00 which is
df['UTCTime'][0]+datetime.timedelta(hours=dateDic[df['CountryCode'][0]])
I have tried to do it with a for loop but since I have more than 1 million rows it's not efficient. I have looked into the apply function but I can't seem to be able to put it to take inputs from two different columns.
Can anyone help me?
Without having a more concrete example its difficult but try this:
pd.to_timedelta(df.CountryCode.map(dateDict), 'h') + df.UTCTime
I'm working with creating excel sheets using python. I'm trying to use a nested for loop to fill in some cells on a spreadsheet and it's not going well. What I want it to do is for each row in a given list of rows I want it to enter an even number into the cell. So basically it should look something like this:
2
4
6
8
etc. (One value per cell)
but instead it comes out like:
24
24
24
24
All the cells have the same value.
Aside from the obvious formatting issues (I'm not finished with the formatting part), it prints the last number in the nested loop for every single cell. From my testing it it appears to be fully executing the inner loop for every cell. I'm using XlsWriter if that helps. I'm not sure how to get it to stop.I'm guessing it's pretty obvious but I haven't done any actual "programming" in years so the solution is eluding me. Here's the loop in question:
for items in purple_rows:
riser_cable.write(items,0,'Company Name',format8)
riser_cable.write(items,1,None,format8)
riser_cable.write(items,2,None,format8)
riser_cable.write(items,3,'Riser',format8)
for i in range(2,26,2):
riser_cable.write(items,4,i,format8)
print(i)
The last 3 lines are ones causing problems.
Thanks for the help!
Edit: The sheet should look like this http://imgur.com/odSaT2D but the code presently turns the entire "Port" column to 24.
Your line:
for i in range(2,26,2):
riser_cable.write(items,4,i,format8)
Writes all the numbers into the same cell. You therefore see only the last number, 24. This is because the item variable is not increased. Try
for i,items in enumerate(purple_rows):
riser_cable.write(items,4,(i*2) % 25,format8).
This should increase item, and put a different value in each row.
the looping convention in python is exclusive so it loops from 2 to 26, not including 26
otherwise, your loop is fine
riser_cable.write(items,4,i,format8)
it seems you are just updating the 4th column with 2,4,...,24. You would have to increment the column index as well
Try this
for i in range(1,13):
riser_cable.write(items,3+i,i*2,format8)
print(i)
I figured out the issue. I ended up changing the code to include a count so it's:
count=0
for items in purple_rows:
count+=2
riser_cable.write(items,4,count,format8)
riser_cable.write(items,10,count,format8)
if count==24:
count=0
Thanks everyone!
That fixed the issue