How do I solve "'subset' must be logical"? - subset

So, I have a dataframe, and within this dataframe I have a variable called 'parties', and the values within this variable is: 1, 2, 3, 4, 5, 6, 7, 8. Every value stands for a specific party. For example, 1 = the Liberal Party.
I want to move the values/parties '2' and '5' to a new dataframe. I have tried,
newdataframe <- subset(dataframe, parties = 2,5)
but I get the following message:
Error in subset.data.frame(subsetdata1, v4 = 2, 5) :
'subset' must be logical
Any advice how to solve this?

Related

'if' 'or'- statement in dictionary always returns TRUE

I have this python dictionary:
event_dict = {
'False': 1,
'Hit': 2,
'MP1': 3,
'MP2': 4,
'MP3': 5,
'M_False': 6,
'M_Hit': 7,
'OGT': 8,
'PMC': 9,
'S 4': 10,
'actiCAP Data On': 11,
'boundary': 12
}
And I wrote this code to check if the entries "TriEVE", "TriODD", "TriPMC" are in the dictionary (They're not!):
if "TriEVE" or "TriODD" or "TriPMC" in event_dict:
print('THIS SESSION HAS BAD ANNOTATIONS!!!!!!!')
The code returns:
THIS SESSION HAS BAD ANNOTATIONS!!!!!!!
I tried to use the 'if'-statement with just one input (without 'or'), like:
if "TriEVE" in event_dict:
print('THIS SESSION HAS BAD ANNOTATIONS!!!!!!!')
print(subject)
The code returns nothing, as expected.
Why can't I use 'or'-statements in this case? Is there a smarter way of searching for more than one dictionary entry at once?
In this case, you want
if "TriEVE" in event_dict.keys() or "TriODD" in event_dict.keys() or "TriPMC" in event_dict.keys():
this is because anything not-zero or non-None is evaluated to True in Python
Since it seems that you wanted to search the keys of the dict, you have to use .keys() or .values() if you want to look at values. The object itself isn't useful in this context

How to find the number of rows in a namedtuple collection?

I have the following code:
Action = namedtuple('Action', 'name index delta_i delta_j')
up = Action('up', 0, -1, 0)
down = Action('down', 1, 1, 0)
left = Action('left', 2, 0, -1)
right = Action('right', 3, 0, 1)
I know there are 4 actions in the collection Action.
But what if I don't know? What Python code do I use to find out?
UPDATE
I have found out from the answers that there is no answer to this question.
Action is a class rather than a collection. I am tempted to delete this question, although it may help someone like me who is new to Python.
It depends on which object you wish to extract the length from.
From one of the instances:
size = len(up)
From the generated class itself, you can do e.g.
size = len(Action._fields) # try print(Action._fields)
From the string used to create the class:
fields = 'name index delta_i delta_j'
size = len(fields.split()) # again, try print(fields.split())

can't remove some duplicate elements from a list in python

well I was trying to remove duplicate items from a list so it has unique items and I also wanted to use for and if my code went so well but in one condition I faced something I don't understand. this is the example :
a = [1,2,2,3,3,3,21,21,16,20,28,28,7]
for x in a:
if a.count(x) > 1:
for z in range(a.count(x)):
a.remove(x)
print(a)
[1, 21, 21, 16, 20, 7]
I don't understand why !! It removes 2,3,28 which was predicted but not 21 !
any help would be great , thanks.
The best solution for this case is using set(). If you do list(set(a)) it will remove all duplicates.
Notice that set() is not the same as list() so be sure to turn it back to a list if you want to keep using list methods.
About your code, the problem with your code is that you're running on the list as you're changing it.
While you run over the items the indexes changes and that's why you miss some of the items.
You can see more clearly what happens if you add a print to understand what's x's value:
a = [1,2,2,3,3,3,21,21,16,20,28,28,7]
for x in a:
print(x)
if a.count(x) > 1:
for z in range(a.count(x)):
a.remove(x)
I believe your issue is that you are changing the list while you're looping over it
Try using a.copy() to create a new copy of the list to loop over like so.
a = [1,2,2,3,3,3,21,21,16,20,28,28,7]
for x in a.copy():
if a.count(x) > 1:
for z in range(a.count(x)):
a.remove(x)
print(a)
This code will output
[1, 16, 20, 7]

Returning a list of N dictionary keys that have the maximum integer values

my_dict = {'label': 6, 'label_2': 5, 'label_3': 9, 'label_4': 12}
I would like to create a list that will contain the top 2 (or 3, or 4, or 50... this will vary) dictionary keys, according to their highest values. So in the example above if I wanted the top 2, I should get:
['label_3', 'label_4']
for top 3 I should get:
['label', 'label_3', 'label_4']
And so on.
After reading some other stackoverflow threads, I've been experimenting with heapq, but can't get it to work the way I want. Would appreciate some help.
Of course, the moment I post here, I find a solution (thanks to the heapq documentation). This works:
my_list = heapq.nlargest(3, my_dict, key=my_dict.get)
This will go over my_dict and return the keys with the 3 largest values.
Thanks.

Python3.4 Dictionary value replacement issue

I have some code which takes a list of dictionaries and creates another list of dictionaries.
Each dictionary in the list has two key/value pairs "ID" and "opcode", where "opcode" is a 32 bit number.
My code needs to create a second list of dictionaries where the opcodes are separated, i.e. a dictionary with opcode=5 would become two dictionaries with opcode=1 and opcode=4.
(opcode is a 32 bit number and my requirement is that only 1 bit is high, ie opcode=1,2,4,8,16 etc)
I've simplified the problem into the following; my code needs to turn this:
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
into this:
part_=[{"ID":1,"opcode":4},{"ID":2,"opcode":1},{"ID":2,"opcode":4},{"ID":3,"opcode":2},{"ID":3,"opcode":4}]
Currently my code is the following
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(i)
part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)
The output of the code is:
{'opcode': 4, 'ID': 1}
{'opcode': 1, 'ID': 2}
{'opcode': 2, 'ID': 3}
Interestingly if I modify the code slightly so that the value modification line is not there, the extra dictionaries are created, but obviously the opcode is not correct.
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part=[{"ID":1,"opcode":4},{"ID":2,"opcode":5},{"ID":3,"opcode":6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(i)
#part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)
The output is
{'ID': 1, 'opcode': 4}
{'ID': 2, 'opcode': 5}
{'ID': 2, 'opcode': 5}
{'ID': 3, 'opcode': 6}
{'ID': 3, 'opcode': 6}
I can get around the issue by going about the problem a different way, but in the interest in learning what is going on I'm out of my depth.
This is caused as when you append i to the new list you do not create a copy of the dictionary instead you add a reference to the original dictionary. This means that when you change the dictionary in the next line you also change value in part. This causes the loop not to match the any more parts of the opcode. You can see this if you print out the values of part at the end of your code.
The python documentation explains this as:
Assignment statements in Python do not copy objects, they create bindings between a target and an object. For collections that are mutable or contain mutable items, a copy is sometimes needed so one can change one copy without changing the other.
Reference
You can fix this by creating a copy of the dictionary when you append it. This will allow you change the value without affecting the original dictionary. Python allows you to copy objects using the copy module (Documentation).
Just import copy and then do part_.append(copy.copy(i)) instead of part_.append(i).
import copy
def bit_set(theNumber,bit):
return theNumber&(1<<bit)!=0
part = [{"ID": 1, "opcode": 4}, {"ID": 2, "opcode": 5}, {"ID": 3, "opcode": 6}]
part_=[]
for i in part:
for j in range(32):
if bit_set(i["opcode"],j):
part_.append(copy.copy(i))
part_[-1]["opcode"]=(1<<j)
for i in part_:
print(i)

Resources