arcgis python index of layer within a dataframe - python

I am new to python and I have searched everywhere but I can not find an explicit method to get the index of a layer in the map, and more specifically in a given dataframe.
I have been able to list the layers using ListLayers function.
I have using this code which does not work, and i also did not really expect it to work, but I have tried other things and nothing, so I decided to ask the group, Thanks
import arcpy
mxd = arcpy.mapping.MapDocument(r"D:\PythonTest\Data\MyMap.mxd")
df = arcpy.mapping.ListDataFrarames(mxd, "MTM8")[0]
listlayer = arcpy.mapping.ListLayers(mxd, "", df)
for lyr in listlayer:
print lyr.index(lyr)

The listlayers method returns a list of ArcGIS layer objects. In your expression you are searching for the text name of the object and not the object itself. This is why python will return ""lyr" is not in the list"
I'm also trying to work out the correct method for this. What i have done thus far is to create two lists:
a list of layer objects (Layerlist)
a list of layer object names (retrievelist)
I can then pull out the layer object from layerlist by searching the text names in retrievelist retreiving the index and then slicing layerlist with that index position. It seems "unclean" but since both list are in the exact same order it works.
I'd be interested in any cleaner solutions to this

Related

Problem re-creating a forloop from a Kaggle competition

Recently for a course at University, our teacher asked us to re-create one of Kaggle's competitions. I chose to do this one.
I was able to follow the tutorial relatively well, until I reached the for loop they wrote to clean the text in the data frame. Here it is:
# Get the number of reviews based on the dataframe column size
num_reviews = train["review"].size
# Initialize an empty list to hold the clean reviews
clean_train_reviews = []
# Loop over each review; create an index i that goes from 0 to the length
# of the movie review list
for i in xrange( 0, num_reviews ):
# Call our function for each one, and add the result to the list of
# clean reviews
clean_train_reviews.append( review_to_words( train["review"][i] ) )
My problem is when they use 'xrange' in the loop, since that was never assigned to anything during the tutorial and is, therefore, returning an error when I try to run the code. I also checked the code provided by the author on github and they did the exact same thing. So, my question is: Is this simply a mistake on their end or am I missing something? If I am not missing anything, what should be in the place of'xrange'?
I've tried assigning the relevant dataframe column to a variable I can then use here, but I then get a TypeError, stating 'Series' object is not callable. My knowledge in Python is a bit elementary still, so I apologize if I am simply missing something obvious. Appreciate any help!
range and xrange are both python functions, the only thing, xrange is used only in python 2.
Both are implemented in different ways and have different characteristics associated with them. The points of comparison are:
Return Type:
Type 'list',
Type 'xrange'
Memory:
Big size,
Small size
Operation Usage:
As range() returns the list, all the operations that can be applied on the list can be used on it. On the other hand, as xrange() returns the xrange object, operations associated to list cannot be applied on them, hence a disadvantage.
Speed:
Because of the fact that xrange() evaluates only the generator object containing only the values that are required by lazy evaluation, therefore is faster in implementation than range().
More info:
source
You are probably having this issue because you are using python3.
Just use range function instead.

variable dataframe name - loop works by itself, but not inside of function

I have dataframes that follow name syntax of 'df#' and I would like to be able to loop through these dataframes in a function. In the code below, if function "testing" is removed, the loop works as expected. When I add the function, it gets stuck on the "test" variable with keyerror = "iris1".
import statistics
iris1 = sns.load_dataset('iris')
iris2 = sns.load_dataset('iris')
def testing():
rows = []
for i in range(2):
test=vars()['iris'+str(i+1)]
rows.append([
statistics.mean(test['sepal_length']),
statistics.mean(test['sepal_width'])
])
testing()
The reason this will be valuable is because I am subsetting my dataframe df multiple times to create quick visualizations. So in Jupyter, I have one cell where I create visualizations off of df1,df2,df3. In the next cell, I overwrite df1,df2,df3 based on different subsetting rules. This is advantageous because I can quickly do this by calling a function each time, so the code stays quite uniform.
Store the datasets in a dictionary and pass that to the function.
import statistics
import seaborn as sns
datasets = {'iris1': sns.load_dataset('iris'), 'iris2': sns.load_dataset('iris')}
def testing(data):
rows = []
for i in range(1,3):
test=data[f'iris{i}']
rows.append([
statistics.mean(test['sepal_length']),
statistics.mean(test['sepal_width'])
])
testing(datasets)
No...
You should NEVER make a sentence like I have dataframes that follow name syntax of 'df#'
Then you have a list of dataframes, or a dict of dataframe, depending how you want to index them...
Here I would say a list
Then you can forget about vars(), trust me you don't need it... :)
EDIT :
And use list comprehensions, your code could hold in three lines :
import statistics
list_iris = [sns.load_dataset('iris'), sns.load_dataset('iris')]
rows = [
(statistics.mean(test['sepal_length']), statistics.mean(test['sepal_width']))
for test in list_iris
]
Storing as a list or dictionary allowed me to create the function. There is still a problem of the nubmer of dataframes in the list varies. It would be nice to be able to just input n argument specifying how many objects are in the list (I guess I could just add a bunch of if statements to define the list based off such an argument). **EDIT: Changing my code so that I don't use df# syntax, instead just putting it directly into a list
The problem I was experiencing is still perplexing. I can't for the life of me figure out why the "test" variable performs as expected outside of a function, but inside of a function it fails. I'm going to go the route of creating a list of dataframes, but am still curious to understand why it fails inside of the function.
I agree with #Icarwiz that it might not be the best way to go about it but you can make it work with.
test=eval('iris'+str(i+1))

BatchDataset not subscriptable when trying to format Python dictionary as table

I'm working through the TensorFlow Load pandas.DataFrame tutorial, and I'm trying to modify the output from a code snippet that creates the dictionary slices:
dict_slices = tf.data.Dataset.from_tensor_slices((df.to_dict('list'), target.values)).batch(16)
for dict_slice in dict_slices.take(1):
print (dict_slice)
I find the following output sloppy, and I want to put it into a more readable table format.
I tried to format the for loop, based on this recommendation
Which gave me the error that the BatchDataset was not subscriptable
Then I tried to use the range and leng function on the dict_slices, so that i would be an integer index and not a slice
Which gave me the following error (as I understand, because the dict_slices is still an array, and each iteration is one vector of the array, not one index of the vector):
Refer here for solution. To summarize we need to use as_numpy_iterator
example = list(dict_slices.as_numpy_iterator())
example[0]['age']
BatchDataset is a tf.data.Dataset instance that has been batches by calling it's .batch(..) method. You cannot "index" a tensorflow Dataset, or call the len function on it. I suggest iterating through it like you did in the first code snippet.
However in your dataset you are using .to_dict('list'), which means that a key in your dictionary is mapped to a list as value. Basically you have "columns" for every key and not rows, is this what you want? This would make printing line-by-line (shown in the table printing example you linked) a lot more difficult, since you do not have different features in a row. Also it is different from the example in the official Tensorflow code, where a datapoint consists of multiple features, and not one feature with multiple values.
Combining the Tensorflow code and pretty printing:
columns = list(df.columns.values)+['target']
dict_slices = tf.data.Dataset.from_tensor_slices((df.values, target.values)).batch(1) # batch = 1 because otherwise you will get multiple dict_slice - target pairs in one iteration below!
print(*columns, sep='\t')
for dict_slice, target in dict_slices.take(1):
print(*dict_slice.numpy(), target.numpy(), sep='\t')
This needs a bit of formatting, because column widths are not equal.

Is there a tensor eqiv to python's list.count()

I'm attempting to do all my input pipeline work in tensorflow. This includes transforming the examples into the types required by the classifier.
I just learned I can't iterate over a string tensor like I would do with a standard python list. My specific question is "is there a tf function for testing the existence of a constant value within a tensor?" Of course there may be a better way to do this (I'm new to tf and python).
# creating a unique list of tokens (python)
a_global = []
a = [...]
for token in a:
if a_global.count(token) == 0:
a_global.append(token)
I'm indexing string tokens so I can essentially convert them into integers using the token's position within the list as its new value. That snippet will not work when "a" is a tensor, so I'm trying tf.map_fn() instead, but I don't know how to replicate the IF statement predicate. Can someone point me in the right direction?
tf ver 1.8
If you don't need gradients for this operation (which I guess you don't for preprocessing stuff), the easiest could be to use tf.py_func. It essentially is able to wrap numpy code snippets into TensorFlow ops.
If that doesn't work for you, look at this post to count occurrences. Then you could use tf.cond to replicate the if statement.

Maya, Python, How do i get the name of an object based on vertex selection?

I got the code working like this until i realized that the vertex index changes for geometry with over 100 vertices...
I assumed i could just split the string and everything would be dandy
import maya.cmds as mc
selPoints = mc.ls(sl = True) # list of names of selected vertices
objName = (str(selPoints[0]))[:-9]
print selPoints
print objName
Heres what it returned:
[u'pCylinder25.vtx[4]', u'pCylinder25.vtx[24]']
pCylinder
I'm trying to hack off the portion with '.vtx[integer]'
I may be going about this completely wrong, and there may be a dead simple way to do this.
Thanks
You can get the object from any valid selection string with the -o flag:
cmds.ls("pCube1.vtx[0]", o=True)
# pCubeShape1
Note that will be the shape, not the transform -- that's Maya being pedantic but it is correct. The transform would be
cmds.listRelatives(cmds.ls("pCube1.vtx[0]", o=True), p=True)
You may also find it helpful to split the components using partition:
object, _, component = "pCube1.vtx[0]".partition(".")
where the _ is python slang for 'ignore me'.
Wouldn't it be awesome if it were easy to get the object from Maya? From experience, I know it can be frustrating since MEL/maya.cmds doesn't use an object-oriented approach.
Anyhow, you should refer to the documentation often for more info on the variety of string methods you can use. Really comes in handy all the time!
To answer your question, you can use .split or .find, whichever you prefer.
print selPoints[0].split('.vtx')[0]
print selPoints[0][0:selPoints[0].find('.vtx')]
The split method returns a list of strings created by the delimiter string '.vtx'. Then, taking the first element from that list will always be the object name.
The find method returns the index of the substring '.vtx', so the second example simply uses slicing syntax to return the correct string.
just for stuff, using vanilla maya commands:
as mentioned with ls:
cm.ls("pCube1.vtx[0]", o=1) # will return shape pCubeShape1
with plugNode (opposite plugAttr):
cm.plugNode("pCube1.vtx[0]") # will return transform pCube1

Categories