How to edit multi-person objects in R - r

I find the following behaviour of the R person object rather unexpected:
Let's create a multi-person object:
a = c(person("Huck", "Finn"), person("Tom", "Sawyer"))
Imagine we want to update the given name of one person in the object:
a[[1]]$given <- 'Huckleberry'
Then if we inspect our object, to my surprise we have:
> a
[1] " <> [] ()" "Tom Sawyer"
Where'd Huckleberry Finn go?! (Note that if we try this with just a single person object, it works fine.) Why does this happen?
How can we do the above so that we get the more logical behavior of correcting just the first name?

The syntax you want here is
a <- c(person("Huck", "Finn"), person("Tom", "Sawyer"))
a[1]$given<-"Huckleberry"
a
#[1] "Huckleberry Finn" "Tom Sawyer"
A group of people is still a "person" and it has it's own special indexing function [.person and concat function c.person so it has perhaps different behavior than you were expecting. The problem was that [[ ]] was messing with the underlying hidden list.
Actually, it's interesting because they've overloaded nearly all the indexing methods for person but not the [<- or [[<- and that's really what's causing the error. Because up to here, we're the same
`$<-`(`[`(a,1), "given", "Huckleberry") #works
`$<-`(`[[`(a,1), "given", "Huckleberry") #works
but when we get to
`[<-`(a, 1, `$<-`(`[`(a,1), "given", "Huckleberry")) #works
`[[<-`(a, 1, `$<-`(`[[`(a,1), "given", "Huckleberry")) #no work
we see a difference. The special wrapping/unwrapping that happens during retrieval does not happen during assignment.
So what's going on is that a "person" is always a list of lists. The outer list holds all the people and the inner lists hold the data. You can think of the data like this
x<-list(
list(name="a"),list(name="b")
)
y<-list(
list(name="c")
)
where x is a collection of two people and y is a "single" person. When you do
x[1]<-y
x
you end up with
list(
list(name="c"),list(name="b")
)
since you're replacing a list with a list which is how [ indexing works with lists. But if you try to replace the element at [[1]] with a list of lists, that list will get nested. For example
x[[1]]<-y
x
becomes
x<-list(
list(list(name="c")),list(name="b")
)
And that extra level of nesting is what's confusing R when it goes to print the person in the first position. That first person won't have any named elements at the second level, so when it goes to print, it will return
emptyp <- structure(list(structure(list(), class="person")), class="person")
utils:::format.person(emptyp)
# " <> [] ()"
which gives is the symbols where it's trying to place the name, e-mail address, role, and comment.

Related

named Element-wise operations in R

I am a beginner in R and apologize in advance for asking a basic question, but I couldn't find answer anywhere on Google (maybe because the question is so basic that I didn't even know how to correctly search for it.. :D)
So if I do the following in R:
v = c(50, 25)
names(v) = c("First", "Last")
v["First"]/v["Last"]
I get the output as:
First
2
Why is it that the name, "First" appears in the output and how to get rid of it?
From help("Extract"), this is because
Subsetting (except by an empty index) will drop all attributes except names, dim and dimnames.
and
The usual form of indexing is [. [[ can be used to select a single element dropping names, whereas [ keeps them, e.g., in c(abc = 123)[1].
Since we are selecting single elements, you can switch to double-bracket indexing [[ and names will be dropped.
v[["First"]] / v[["Last"]]
# [1] 2
As for which name is preserved when using single bracket indexing, it looks like it's always the first (at least with the / operator). We'd have to go digging into the C source for further explanation. If we switch the order, we still get the first name on the result.
v["Last"] / v["First"]
# Last
# 0.5

Python - code works, but I don't know why

Basically I want someone to give me a simple rundown of how this bit of python code works. Much appreciated
vari :
kw1 = ['keyword1', 'keyword2']
problem = input("Detect keywords from list\n")
main :
if set(kw1).intersection(problem.split()):
print(" Kw found. ")
else:
print(" Keywords not found. ")
A lot of things there.
First, when you call input you're asking for the user to give you an input string.
When you use split() on it you transform it into a list of strings, by separating the input string based on the empty spaces, so that "bla bli blo".split() gives you ["bla","bli","blo"].
Then, when you call set(my_list), it will transform my_list into a set, which is a mathematical construct without any duplicates and which responds to operators like union, intersection and so on.
Finally, when you compare your set (made from splitting the user input) to a list of keywords, if there are no matches (so none of the keywords in the list appreared directly in the user input), then it will give you an empty set and that will be considered as false by the if. So if set(["bla","bli","blo"]).intersection(["blu"]) will not activate, but if set(["bla","bli","blo"]).intersection(["blu","blo"]) will, as it is not an empty set.
Note that if you want to recognize keywords inside words, this method will NOT work. For instance, if you're looking for keywords kw1=['car','truck','bike'] and the user inputs cars trucks bikes, none of the keywords will be recognized, because the split() will split along empty spaces, giving you ['cars','trucks','bikes'] and 'cars'!='car'...

Make a list from ls(pattern="") [R]

The ls(pattern="") function is very useful for me, since my list of objects seem to keep growing and growing. I am curious if this feature can be more useful.
For example, let's say i have 4 objects,
a.c<-1
b.c<-2
c.c<-3
d.c<-4
Now i use the useful ls(pattern="") function
ls(pattern=".c")
Now i try to make a list
list(ls(patter=".c"))
But it doesn't give me anything useful( "a.c" "b.c" "c.c" "d.c" ). I want either of these two outputs
1,2,3,4
OR
a.c, b.c, c.c, d.c
A couple of issues:
1) The . in ".c" gets ignored, you need to "escape" it:
ls(pattern="\\.c")
Otherwise it will return all objects with c regardless of having a period.
2) ls returns names of objects as character. To get the value of an object based on its name you need the function get:
lapply(ls(pattern="\\.c"), get)
3) As joran mentioned in the comments, it's much better to keep objects associated with each other in lists:
List.c = list(a.c=1, b.c=2, c.c=3, d.c=4)

The arcane formals(function(x){})$x

What is the object formals(function(x){})$x?
It's found in the formals of a function, bound to arguments without default value.
Is there any other way to refer to this strange object? Does it have some role other than representing an empty function argument?
Here are some of its properties that can be checked in the console:
> is(formals(function(x){})$x)
[1] "name" "language" "refObject"
> formals(function(x){})$x
> as.character(formals(function(x){})$x)
[1] ""
EDIT: Here are some other ways to get this object:
alist(,)[[1]]
bquote()
quote(expr=)
Background: What is formals(function(x) {})?
Well, to start with (and as documented in ?formals) , formals(function(x) {}) returns a pairlist:
is(formals(function(x){}))
# [1] "pairlist"
Unlike list objects, pairlist objects can have named elements that contain no value -- a very nice thing when constructing a function that has a possibly optional formal argument. From ?pairlist:
tagged arguments with no value are allowed whereas ‘list’ simply ignores them.
To see the difference, compare alist(), which creates pairlists, with list() which constructs 'plain old' lists:
list(x=, y=2)
# Error in list(x = , y = 2) : argument 1 is empty
alist(x=, y=2)
# $x
#
# $y
# [1] 2
Your question: What is formals(function(x) {})$x?
Now to your question about what formals(function(x) {})$x is. My understanding is in some sense its real value is the "empty symbol". You can't, however, get at it from within R because the "empty symbol" is an object that R's developers -- very much by design -- try to entirely hide from R users. (For an interesting discussion of the empty symbol, and why it's kept hidden, see the thread starting here).
When one tries to get at it by indexing an empty-valued element of a pairlist, R's developers foil the attempt by having R return the name of the element instead of its verbotten-for-public-viewing value. (This is, of course, the name object shown in your question).
It's a name or symbol, see ?name, e.g.:
is(as.name('a'))
#[1] "name" "language" "refObject"
The only difference from your example is that you can't use as.name to create an empty one.

in R, extract part of object from list

I'm just learning R and having a hard time wrapping my head around how to extract elements from objects in a list. I've parsed a json file into R giving me list object. But I can't figure out how, from there, to extract various json elements from the list. here's a truncated look at how my data appears after parsing the json:
> #Parse data into R objects#
> list.Json= fromJSON(,final.name, method = "C")
> head(listJson,6)
[[1]]
[[1]]$contributors
NULL
[[1]]$favorited
[1] FALSE
...[truncating]...
[[5]]
[[5]]$contributors
NULL
[[5]]$favorited
[1] FALSE
I can figure out how to extract the favorites data for one of the objects in the list
> first.object=listJson[1]
> ff=first.object[[1]]$favorited
> ff
[1] FALSE
But I'm very confused about how to extract favorited for all objects in the list. I've looked into sappily, is that the correct approach? Do I need to put the above code into a for...next loop?
sapply is going to apply some function to every element in your list. In your case, you want to access each element in a (nested) list. sapply is certainly capable of this. For instance, if you want to access the first child of every element in your list:
sapply(listJson, "[[", 1)
Or if you wanted to access the item named "favorited", you could use:
sapply(listJson, "[[", "favorited")
Note that the [ operator will take a subset of the list you're working with. So when you access myList[1], you still have a list, it's just of length 1. However, if you reference myList[[1]], you'll get the contents of the first space in your list (which may or may not be another list). Thus, you'll use the [[ operator in sapply, because you want to get down to the contents of the list.

Resources