Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract Post Reaction Metrics #121

Open
wants to merge 48 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
97e01f0
version bump
pablobarbera Jul 27, 2016
27314df
Merge pull request #81 from pablobarbera/dev
pablobarbera Jul 29, 2016
a20c155
Update getInsights.R
mkoch15 Aug 3, 2016
37e7780
Update getInsights.R
mkoch15 Aug 3, 2016
7693ba1
typo in getCommentReplies example
pablobarbera Aug 17, 2016
17179d9
Merge pull request #84 from mkoch15/master
pablobarbera Aug 17, 2016
a2d9020
added 'story' field to getPage (fixes #83)
pablobarbera Aug 17, 2016
da324e8
version bump
pablobarbera Aug 17, 2016
bfbe3cb
fix #88 getPage does not work when posts had no reactions
pablobarbera Oct 24, 2016
d46fa46
Add 'verbose' parameter
stas-malavin Dec 17, 2016
46ca8e2
Merge pull request #95 from stas-malavin/patch-1
pablobarbera Dec 29, 2016
c38879d
version bump (v 0.6.11)
pablobarbera Jan 4, 2017
0c68dd9
fixes #96
pablobarbera Jan 4, 2017
9343a08
Update getPage.R
stas-malavin Jan 5, 2017
bcfa81e
Merge pull request #98 from stas-malavin/patch-1
pablobarbera Jan 6, 2017
c396bbb
Added reactions option to getPosts
vanatteveldt Jan 15, 2017
7bffdbb
Merge pull request #103 from vanatteveldt/master
pablobarbera Jan 21, 2017
e887194
added support for multiple API versions
pablobarbera Jan 21, 2017
c3e60de
version bump
pablobarbera Jan 21, 2017
a46e99d
added note re: comments_count (fix #104)
pablobarbera Jan 21, 2017
c14e705
Add explicit scope argument to fbOAuth
vanatteveldt Feb 15, 2017
6fec99f
Add getPageToken function to get page access tokens (e.g. for insights)
vanatteveldt Feb 15, 2017
7a33deb
Merge pull request #107 from vanatteveldt/master
pablobarbera Feb 17, 2017
800cf34
version bump; wouter as ctb
pablobarbera Feb 17, 2017
c79f0e8
fixes #117 (thanks @josefslerka !)
pablobarbera Apr 22, 2017
3a797e7
version bump
pablobarbera Apr 22, 2017
9ef68ee
update searchPages (fixes #114)
pablobarbera May 25, 2017
be19961
fixes #115 (do not add API version if already in URL)
pablobarbera May 25, 2017
c901b62
should fix #116
pablobarbera May 25, 2017
3725c0d
fixes #88 (passing api arg to getReactions in getPage)
pablobarbera May 25, 2017
e8552d6
added getEvents (fixes #112)
pablobarbera May 25, 2017
1e7e4e4
CRAN version v0.6.15
pablobarbera May 25, 2017
539f4c1
added param name to getLikes in README demo code
Jun 1, 2017
c0978c5
Merge pull request #129 from mkearney/master
pablobarbera Jun 2, 2017
bdc086b
CRAN version bump
pablobarbera Jun 2, 2017
0f16299
fixes #128 (searchGroups with more than 25 results)
pablobarbera Jun 2, 2017
7c08ae4
documentation updates + version bump
pablobarbera Jun 2, 2017
88697fe
fixes #138 (getUsers now works w/recent APIs)
pablobarbera Jul 11, 2017
0af6656
fixes #132 (updated documentation)
pablobarbera Jul 11, 2017
0271880
fixes #137 (new getMembers function)
pablobarbera Jul 12, 2017
70c993b
Update getMembers.R
yanturgeon Jul 12, 2017
c7cd323
Merge pull request #139 from yanturgeon/patch-1
pablobarbera Jul 12, 2017
173257e
fixes error in getPost when no reactions were returned
pablobarbera Jan 26, 2018
45b39c6
fixes #168
pablobarbera Feb 8, 2018
c1325db
update README
pablobarbera Jul 18, 2018
841f6f4
Remove vignette from README
pablobarbera Jul 28, 2018
53c4f7d
Update searchPages.R
MoisesFagundes May 19, 2020
71d934d
Merge pull request #191 from MoisesFagundes/master
pablobarbera May 22, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ _test
.Rapp.history
credentials.dta
creating-credentials.r
.Rproj.user
229 changes: 2 additions & 227 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,232 +1,7 @@
Rfacebook: Access to Facebook API via R
---------

This package provides a series of functions that allow R users to access Facebook's API to get information about public pages, groups, and posts, as well as some of the authenticated user's private data.
Due to recent changes in Facebook's Graph API, all functions of the package now require a working app that has undergone App Review. More details are [available here](https://developers.facebook.com/docs/pages/).

Current CRAN release is 0.6.3. To install the most updated version (0.6.6) from GitHub using devtools, type:

```r
library(devtools)
install_github("pablobarbera/Rfacebook/Rfacebook")
```

Click <a href="https://cran.r-project.org/web/packages/Rfacebook/Rfacebook.pdf">here</a> to read the documentation.

<h3>Installation and authentication</h3>

Rfacebook can be installed directly from CRAN, but the most updated version <a href="https://github.com/pablobarbera/Rfacebook">will always be on GitHub</a>. The code below shows how to install from both sources.

```r
install.packages("Rfacebook") # from CRAN
library(devtools)
install_github("pablobarbera/Rfacebook/Rfacebook") # from GitHub

```

Most API requests require the use of an access token. There are two ways of making authenticated requests with Rfacebook. One option is to generate a temporary token on the <a href="https://developers.facebook.com/tools/explorer/">Graph API Explorer</a>. Then just copy and paste the code into the R console and save it as a string vector to be passed as an argument to any Rfacebook function, as I show below. However, note that this access token will only be valid for two hours. It is possible to generate a &#39;long-lived&#39; token (valid for two months) using the `fbOAuth` function, but the process is a bit more complicated. For a step-by-step tutorial, check this <a href="http://thinktostart.wordpress.com/2013/11/19/analyzing-facebook-with-r/">fantastic blog post</a> by <a href="https://twitter.com/JulianHi">JulianHi</a>.

```r
# token generated here: https://developers.facebook.com/tools/explorer
token <- 'XXXXXXXX'
me <- getUsers("me", token, private_info=TRUE)
me$name # my name
# [1] "Pablo Barberá"
me$hometown # my hometown
# [1] "Cáceres, Spain"

```

The example above shows how to retrieve information about a Facebook user. Note that this can be applied to obtain information about any user (or vector of users) with public profiles -- that is, pages. Both user screen names or IDs can be used as arguments, e.g.:

```r
getUsers(c("barackobama", "donaldtrump"), token)

```

This function cannot be used to obtain profile information for users with private profiles, with the exception of those profiles who are using the application created by the authenticated user. When using a temporary token, only the information of profiles who have ever created a temporary token in the authenticated user's network of friends will be returned.

<h3>Analyzing your network of friends</h3>

The function `getFriends` allows the user to capture information about their Facebook friends, as long as they are using the application created to authenticate with the API. Since user IDs are assigned in consecutive order, it's possible to find out which of our friends was the first one to open a Facebook account.

```r
my_friends <- getFriends(token, simplify = TRUE)
head(my_friends$id, n = 1) # get lowest user ID

```

To access additional information about a list of friends using the token application, you can use the `getUsers` function, which will return a data frame with users' Facebook data. Some of the variables that are available for all users are: gender, language, and country. It is also possible to obtain relationship status, hometown, birthday, and location for our friends if we set `private_info=TRUE`. (Note that language and country are extracted from the `locale` <a href="https://developers.facebook.com/docs/internationalization/">codes</a>.)

```r
my_friends_info <- getUsers(my_friends$id, token, private_info = TRUE)
table(my_friends_info$gender) # gender
table(substr(my_friends_info$locale, 1, 2)) # language
table(substr(my_friends_info$locale, 4, 5)) # country
table(my_friends_info$relationship_status) # relationship status
```

Finally, the function `getNetwork` extracts a list of all the mutual friendships among the friends using the application with which the token was created. This list can be then used to analyze and visualize a Facebook ego network. The first step is to use the `getNetwork` function. If the `format` option is set equal to `edgelist`, it will return a list of all the edges of that network. If `format=adj.matrix`, then it will return an adjacency matrix of dimensions (n x n), with n being the number of friends, and 0 or 1 indicating whether the user in row 'i' is also friends with user in column 'j'.

```r
mat <- getNetwork(token, format = "adj.matrix")
dim(mat) # dimension of matrix
```

This adjacency matrix can then be converted into an igraph object, which facilitates the task of computing measures of centrality, discovering communities, or visualizing the structure of the network. As an illustration, the plot below displays my Facebook ego network, where the colors represent clusters discovered with a community detection algorithm, which clearly overlap with membership in offline communities. This was one of the examples from my <a href='https://github.com/pablobarbera/Rdataviz'>workshop on data visualization with R and ggplot2</a>. The code to replicate it with your own Facebook data is available <a href='https://github.com/pablobarbera/Rdataviz/blob/master/code/05_networks.R'>here</a>. David Smith has also <a href="http://blog.revolutionanalytics.com/2013/11/how-to-analyze-you-facebook-friends-network-with-r.html">posted code to generate a similar network plot</a>.

<center><img src="images/network_plot_final.png" alt="Facebook ego network" style="width: 750px;"/></center>

Note that since version 2.0 of the Graph API, only the friends using the application with which the authenticated token was created are returned by this application. Old versions of the API are no longer available.


<h3>Searching public Facebook posts</h3>

Prior to version 2.0 of the Graph API, it was possible to collect public Facebook posts mentioning specific keywords, using the `searchFacebook` function. This option is no longer available through the public API.

<h3>Analyzing data from a Facebook page</h3>

Facebook pages are probably the best source of information about how individuals use this social networking site, since all posts, likes, and comments can be collected combining the `getPage` and `getPost` functions. For example, assume that we're interested in learning about how the Facebook page <a href="https://www.facebook.com/humansofnewyork">Humans of New York</a> has become popular, and what type of audience it has. The first step would be to retrieve a data frame with information about all of its posts using the code below. To make sure I collect every single post, I set `n` to a very high number, and the function will stop automatically when it reaches the total number of available posts (3,674).

```r
page <- getPage("humansofnewyork", token, n = 5000)
page[which.max(page$likes_count), ]
## from_id from_name
## 1915 102099916530784 Humans of New York
message
## 1915 Today I met an NYU student named Stella. I took a photo of her. (...)
## created_time type
## 1915 2012-10-19T00:27:36+0000 photo
## link
## 1915 https://www.facebook.com/photo.php?fbid=375691212504985&set=a.102107073196735.4429.102099916530784&type=1&relevant_count=1
## id likes_count comments_count
## 1915 102099916530784_375691225838317 894583 117337
## shares_count
## 1915 60528
```

The <a href="https://www.facebook.com/photo.php?fbid=375691212504985&set=a.102107073196735.4429.102099916530784&type=1&relevant_count=1">most popular post ever</a> received almost 900,000 likes and 120,000 comments, and was shared over 60,000 times. As we can see, the variables returned for each post are the same as when we search for Facebook posts: information about the content of the post, its author, and its popularity and reach. Using this data frame, it is relatively straightforward to visualize how the popularity of Humans of New York has grown exponentially over time. The code below illustrates how to aggregate the metrics by month in order to compute the median count of likes/comments/shares per post: for example, in November 2013 the average post received around 40,000 likes.

```r
## convert Facebook date format to R date format
format.facebook.date <- function(datestring) {
date <- as.POSIXct(datestring, format = "%Y-%m-%dT%H:%M:%S+0000", tz = "GMT")
}
## aggregate metric counts over month
aggregate.metric <- function(metric) {
m <- aggregate(page[[paste0(metric, "_count")]], list(month = page$month),
mean)
m$month <- as.Date(paste0(m$month, "-15"))
m$metric <- metric
return(m)
}
# create data frame with average metric counts per month
page$datetime <- format.facebook.date(page$created_time)
page$month <- format(page$datetime, "%Y-%m")
df.list <- lapply(c("likes", "comments", "shares"), aggregate.metric)
df <- do.call(rbind, df.list)
# visualize evolution in metric
library(ggplot2)
library(scales)
ggplot(df, aes(x = month, y = x, group = metric)) + geom_line(aes(color = metric)) +
scale_x_date(breaks = "years", labels = date_format("%Y")) + scale_y_log10("Average count per post",
breaks = c(10, 100, 1000, 10000, 50000)) + theme_bw() + theme(axis.title.x = element_blank())
```

<center><img src="images/humans.png" style="width: 700px;"/></center>

It is also possible to subset posts by date. For example, imagine we want to get only posts posted during 2015:

```r
page <- getPage("humansofnewyork", token, n = 5000, since='2015/01/01', until='2015/12/31')
```

To retrieve more information about each individual post, you can use the `getPost` function, which will return the same variables as above, as well as a list of comments and likes. Continuing with my example, the code below shows how to collect a list of 1,000 users who liked the most recent post, for which we will also gather information in order to analyze the audience of this page in terms of gender, language, and country.

```r
post_id <- head(page$id, n = 1) ## ID of most recent post
post <- getPost(post_id, token, n = 1000, likes = TRUE, comments = FALSE)
```

<h3>Analyzing data from a Facebook group</h3>

Just like public Facebook pages, the data from public groups can also be easily downloaded with the `getGroup` function. Note that this will only work for groups that the authenticated user is a member of.

```r
group <- getGroup("150048245063649", token, n=50)
```


<h3>Extracting personal information</h3>

Rfacebook also allows to read personal information about the authenticated user, such as the list of likes and the content from the Newsfeed. Private information about the user's friends is no longer available through the API.

```r
getLikes('me', token)[1,]
## id names
## 1 687958677914631 FiveThirtyEight
## website
## 1 http://www.fivethirtyeight.com/
```
```r
getNewsfeed(token, n=1)
## 1 51191684997 Rob DenBleyker <NA> <NA>
## message
## 1 Sorry for the late comic, it's up now!\n\nhttp://explosm.net/comics/3512/
## created_time type link
## 1 2014-04-02T12:38:46+0000 link http://explosm.net/comics/3512/
## id likes_count comments_count shares_count
## 1 51191684997_10152084439949998 6942 110 497
```

<h3>Executing other API calls</h3>

To facilitate making API queries not implemented in the current version of the package, I have added the `callAPI` function, which will return an R list with the result of the query. A trivial example:

```r
callAPI("https://graph.facebook.com/v2.0/barackobama?fields=id", token)
```

<h3>Page insights</h3>

Rfacebook provides some limited access to the insights features, available admin accounts of public pages. See the documentation of `getInsights` for more information.


<h3>Updating your Facebook status from R</h3>

Finally, yes:

```r
updateStatus("You can also update your Facebook status from R", token)
## Success! Link to status update:
## http://www.facebook.com/557698085_10152090718708086
```

However, to make this work you will need to get a <a href="http://thinktostart.wordpress.com/2013/11/19/analyzing-facebook-with-r/">long-lived OAuth token</a> first, setting `private_info=TRUE` in the `fbOAUth` function.

<h3>Frequently Asked Questions</h3>

- How can I search public Facebook posts? Can I get any information from users' private profiles? How can I extract my entire network of friends?

All these features used to be available through the API, but unfortunately that's not the case anymore. There's no fix to Rfacebook that could bring back these features.

- I get the following error when I run `getUsers`: `username is deprecated for versions v2.0 and higher`

This is related to the previous question. It is no longer possible to query users by their user names. If the user is a public page, try with the page ID number.

- For any other questions, feature requests, or bugs, please open an issue in this repository.


<script type="text/javascript">

var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-1191254-10']);
_gaq.push(['_trackPageview']);

(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();

</script>
__NOTE:__ This package is currently not being maintained and issues are not monitored.

27 changes: 27 additions & 0 deletions Rfacebook/ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,30 @@
- other minor fixes
2016-07-12 - version 0.6.7
- added getCommentReplies function to scrape nested comments
2016-07-26 - version 0.6.8
- getGroup function now has feed option to return only admin posts
2016-08-16 - version 0.6.9
- added story field to getPage
2016-10-23 - version 0.6.10
- fixed bug in getPage with reactions=T in posts with no reactions
2016-12-28 - version 0.6.11
- added verbose option to getPage
2017-01-21 - version 0.6.12
- added support for reactions in getPost
- added support for multiple API versions in callAPI
2017-02-17 - version 0.6.13
- fixes in getInsights
2017-04-21 - version 0.6.14
- fixes in fbOAuth
2017-05-24 - version 0.6.15
- adds getEvents
- updates in searchPages
- minor fixes
2017-06-01 - version 0.6.16
- documentation updates
- searchGroups now returns 25+ results
2017-07-11 - version 0.6.17
- getUsers now works with recent versions of API
- getMembers function added (thanks Yan Turgeon)
2018-02-08 - version 0.6.18
- getCommentReplies() returns NA for from field when API does not return it
8 changes: 4 additions & 4 deletions Rfacebook/DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
Package: Rfacebook
Title: Access to Facebook API via R
Description: Provides an interface to the Facebook API.
Version: 0.6.7
Date: 2016-07-12
Version: 0.6.18
Date: 2018-02-08
Author: Pablo Barbera <[email protected]>, Michael Piccirilli
<[email protected]>, Andrew Geisler
<[email protected]>, Andrew Geisler, Wouter van Atteveldt, Yan Turgeon
Maintainer: Pablo Barbera <[email protected]>
URL: https://github.com/pablobarbera/Rfacebook
BugReports: https://github.com/pablobarbera/Rfacebook/issues
Expand All @@ -14,4 +14,4 @@ Depends:
rjson,
httpuv
License: GPL-2
RoxygenNote: 5.0.1
RoxygenNote: 6.0.1
8 changes: 7 additions & 1 deletion Rfacebook/NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ export(callAPI)
export(fbOAuth)
export(getCheckins)
export(getCommentReplies)
export(getEvents)
export(getFQL)
export(getFriends)
export(getGroup)
export(getInsights)
export(getLikes)
export(getMembers)
export(getNetwork)
export(getNewsfeed)
export(getPage)
export(getPageToken)
export(getPost)
export(getReactions)
export(getShares)
Expand All @@ -23,4 +26,7 @@ export(updateStatus)
import(httpuv)
import(httr)
import(rjson)
importFrom("utils", "URLencode", "packageVersion", "setTxtProgressBar", "txtProgressBar")
importFrom(utils,URLencode)
importFrom(utils,packageVersion)
importFrom(utils,setTxtProgressBar)
importFrom(utils,txtProgressBar)
3 changes: 2 additions & 1 deletion Rfacebook/R/Rfacebook-package.R
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
#' @name Rfacebook-package
#' @aliases Rfacebook
#' @docType package
#' @author Pablo Barbera \email{pablo.barbera@@nyu.edu}
#' @author Pablo Barbera \email{pbarbera@@usc.edu}
#' @import httr rjson httpuv
#' @importFrom utils URLencode packageVersion setTxtProgressBar txtProgressBar
NULL

Loading