<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/do-tweeps-with-more-followers-follow-tweeps-with-more-followers-by-ellis2013nz/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://ellisp.github.io/blog/2018/02/24/following-followers"> Peter's stats stuff - R</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>Branko Milanovic <a rel="nofollow" href="https://twitter.com/BrankoMilan/status/964303658790866944" target="_blank">asked on Twitter</a>:</p>
<blockquote>
<p>Idea for a paper: “Homogamy” on Twitter. Do people with more followers follow people with more followers?</p>
</blockquote>
<p>I don’t have time to write a paper but I was sufficiently interested to want to blog about it. The consensus in the replies was “of course they do”, with the claim that Twitter is well known for being assortative. Oh, here’s some terminology:</p>
<ul>
<li><em>homogamy</em> – in-breeding, or (in sociology) marriage between individuals who are, in some culturally important way, similar to eachother</li>
<li><em>assortative</em> – a preference for a network’s nodes to attach to others that are similar in some way.</li>
</ul>
<p>The idea of assortativity in a network is basically that popular people (or whatever a node is) hang out with eachother and form lots of connections.</p>
<p>First, let’s cut to the chase. Turns out that in fact, looking at the trimmed mean number of followers of the people that Twitter users follow, the relationship with the number of followers of the original person is not straightforward:</p>
<p><img width="100%" src="http://ellisp.github.io/img/0118-main-scatter.svg"></p>
<p>In fact, you could say that generally, the more followers you have, the <em>less</em> followers the people you follow have – until a threshold of around 100,000 followers, which makes you one of the giants of Twitter (for a reference point that might mean something to readers of this blog, <a rel="nofollow" href="https://twitter.com/hadleywickham" target="_blank">Hadley Wickham</a> has around 58,000 followers, so more than 100,000 is really a lot). This finding holds with two different methods of sampling people from Twitter, and is confirmed by more sophisticated modelling that looks simultaneously at the number of people one is following and the number of followers they have.</p>
<p>One plausible explanation is that “number of followers” is a proxy for length of engagement on Twitter. When one starts out on Twitter, you are presented with a bunch of suggested popular accounts to follow (eg sports teams, entertainment celebrities, famous media outlets), typically with very high numbers of followers themselves. So on day one, the average number of followers of the people <em>you</em> follow is very high. Over time, the regular user of Twitter follows people (eg your friends) with less followers and the average followers of those people declines. Only for the super-famous, everyone you know or care about is famous and so the homogamy/assortativity thesis kicks in but <em>iff</em> you’re a bit selective about who you follow, and don’t just follow back all your non-entity fans.</p>
<p>The issue (I think) that stops Twitter being highly assortative is the one-way nature of following someone. Katy Perry’s 109 million followers don’t need to ask her permission to follow her; this makes the forming of edges between nodes in the Twitter network fundamentally different to marriage.</p>
<p>So what about the references mentioned in the Twitter exchange after Milanovic’s first tweet on this? What I see in the literature (admittedly after a very cursory glance – I’m pressed for time as I write this) is a bit different. There’s a couple of pieces suggesting <em>happiness</em> is assortative – people who write happy tweets associate with others who do the same, and the same applies to people who write unhappy tweets. Also, the action of replying and retweeting is assortative. But contrary to what some said in the Twitter exchange, I don’t see articles showing that the follow/followed network is assortative.</p>
<p>Let’s go into how I did this.</p>
<h2>A sampling problem</h2>
<p>The first challenge is to get a sample of Twitter users. This is harder than it might seem at first, if the aim is (as it should be) to be representative of the population at large. First challenge is defining that population. Do we mean every Twitter account, every human Twitter account, every account that is used for actively tweeting (why would you restrict it to this, as even reading tweets should surely count?).</p>
<p>There’s no conveniently published population of Twitter users. I’m aware of three broad ways one might go about getting a sample of users:</p>
<ol>
<li>You could do the equivalent of “random digit dialling”, making up numeric Twitter identification numbers and checking them in the Twitter API for existence. This method is in fact what you find if you google “how do I get a sample of Twitter users” but Twitter have made it effectively impossible by the (hidden) way they assign IDs. I observed ID numbers up to 10^17 and as low as 10^6, and sampling random numbers between those extremes hoping to hit one of the 300 million or so actual users sounds like a recipe for getting nowhere.</li>
<li>You can pick a node and use a snowball sampling method; that is, follow an edge (either a person the first node follows, or a node who follows them) to another node, record what you need to about that person, then follow another edge to a third node, and so on until you have enough people. This is what I did with the sample labelled “snowball sampling along network”.</li>
<li>You can sample a bunch of actual tweets, and treat their authors as your sample. This is what I did with the sample labelled “sample of today’s tweeters”.</li>
</ol>
<p>Method 1 is I think infeasible. Method 2 will oversample users with lots of followers and who follow lots of people – basically, the more networked you are, the more likely you are to be sampled. On the plus side for Method 2, quiet users who lurk but aren’t tweeting these days will have a chance of selection. Method 3 on the other hand will give a very particular slice of users; but it has the advantage of less obvious dependence between the nodes we pick (all they have in common is tweeting in the last couple of minutes of when we harvest them). I was unsure enough about sampling strategy to try them both.</p>
<p>Here’s code to do the sampling, using Jeff Gentry’s <code>twitteR</code> R package. Note that the code that follows isn’t very robust, and took days to run because of Twitter’s rules on maximum downloads via the public API. There’s lots that can go wrong with grabbing data from the Twitter API, hence the extensive and undisciplined use of <code>try()</code> in the code below in an effort to keep the data harvesting going in the face of various quirks .</p>
<p>First, setup. This requires four different pass phrases which associated with your Twitter account (for obvious reasons, blanked out in the below, which stops this script being fully reproducible as-is).</p>
<figure>
<pre><code data-lang="r"><span>library</span><span>(</span><span>tidyverse</span><span>)</span><span>
</span><span>library</span><span>(</span><span>twitteR</span><span>)</span><span>
</span><span>library</span><span>(</span><span>GGally</span><span>)</span><span>
</span><span>library</span><span>(</span><span>mgcv</span><span>)</span><span>
</span><span>consumer_key</span><span> </span><span>&lt;-</span><span> </span><span>&quot;XXXXXXX&quot;</span><span>
</span><span>consumer_secret</span><span> </span><span>&lt;-</span><span> </span><span>&quot;XXXXXXXXXX&quot;</span><span>
</span><span>access_token</span><span> </span><span>&lt;-</span><span> </span><span>&quot;XXXXXXXXXX&quot;</span><span>
</span><span>access_secret</span><span> </span><span>&lt;-</span><span> </span><span>&quot;XXXXXXXXXXX&quot;</span><span>
</span><span>setup_twitter_oauth</span><span>(</span><span>consumer_key</span><span>,</span><span> </span><span>consumer_secret</span><span>,</span><span> </span><span>access_token</span><span>,</span><span> </span><span>access_secret</span><span>)</span></code></pre>
</figure>
<p>As I’m interested in the “average” number of followers of the people a sampled user follows, for each user I sample I’m going to need to find out everyone they follow and estimate how many followers <em>they</em> have. This is the thing that takes time. It also exposes a problem; Twitter won’t let you look at more than a certain number of users at once. That number turns out to be 75,000, as I find out from this experiment with <a rel="nofollow" href="https://twitter.com/search?q=toddcarey&src=typd" target="_blank">Todd Carey</a>:</p>
<figure>
<pre><code data-lang="r"><span>many_following_user</span><span> </span><span>&lt;-</span><span> </span><span>getUser</span><span>(</span><span>&quot;toddcarey&quot;</span><span>)</span><span>
</span><span>many_ids</span><span> </span><span>&lt;-</span><span> </span><span>many_following_user</span><span>$</span><span>getFriendIDs</span><span>()</span><span>
</span><span>length</span><span>(</span><span>many_ids</span><span>)</span><span> </span><span>#</span><span> </span><span>returns</span><span> </span><span>only</span><span> </span><span>75000</span><span> </span><span>ids</span><span>;</span><span> </span><span>I</span><span> </span><span>think</span><span> </span><span>the</span><span> </span><span>most</span><span> </span><span>recent</span><span> </span><span>75</span><span>,</span><span>000</span><span> </span><span>he</span><span>'</span><span>s</span><span> </span><span>followed</span></code></pre>
</figure>
<p>The problem here is that as Carey follows so many people (1.28 million) it’s infeasible to get the details of them all. In fact, it’s infeasible even just to get all their 1.28 million screen names and then sample from those (I’m very happy to estimate “average number of followers of people X follows” from a sample). I’ll have to deal with getting 75,000 users he follows, then sampling from those 75,000. The big problem here is that I think those are the most recent 75,000 people he’s followed. All else being equal, these are likely to be newer Twitter users than the overall population of people he follows, and hence likely to bias downwards my estimate of the average number of followers <em>they</em> have (as newer users will almost certainly have fewer followers on average).</p>
<p>[As an aside, one might wonder what is the point of following 1.28 million people on Twitter; it’s presumably part of a strategy, automated or not, of attracting followers by implicitly agreeing to follow them back. It’s not fully automatic – I established this by following him to see what happened, and nothing did.]</p>
<p>I don’t see what can be done about this, other than note the people who follow more than 75,000 people as potentially suspect in subsequent analysis. There’s not that many of them in my sample anyway.</p>
<p>Anywhere, here’s the code that does the snowball sampling. I start with myself. I take three types of average number of followers of the people X follows: mean (which is highly vulnerable to an arbitrarily large number getting in the sample), 20% trimmed mean and 50% trimmed mean (ie median); but I’m satisfied that 20% trimmed mean is robust and a good measure.</p>
<figure>
<pre><code data-lang="r"><span>#=======================snowball sampling method================
</span><span>
</span><span>follow_data</span><span> </span><span>&lt;-</span><span> </span><span>data_frame</span><span>(</span><span>
</span><span>number_followers</span><span> </span><span>=</span><span> </span><span>integer</span><span>(),</span><span>
</span><span>number_following</span><span> </span><span>=</span><span> </span><span>integer</span><span>(),</span><span>
</span><span>mean_ff</span><span> </span><span>=</span><span> </span><span>numeric</span><span>(),</span><span>
</span><span>trmean_ff</span><span> </span><span>=</span><span> </span><span>numeric</span><span>(),</span><span>
</span><span>median_ff</span><span> </span><span>=</span><span> </span><span>numeric</span><span>(),</span><span>
</span><span>screenName</span><span> </span><span>=</span><span> </span><span>character</span><span>()</span><span>
</span><span>)</span><span>
</span><span># Terminology
# A &quot;friend&quot; is someone you follow
# A &quot;follower&quot; is someone who follows you
</span><span>
</span><span>current_sn</span><span> </span><span>&lt;-</span><span> </span><span>&quot;ellis2013nz&quot;</span><span>
</span><span>set.seed</span><span>(</span><span>124</span><span>)</span><span>
</span><span>for</span><span>(</span><span>i</span><span> </span><span>in</span><span> </span><span>1</span><span>:</span><span>1000</span><span>){</span><span>
</span><span># save latest copy of results in case of crash
</span><span> </span><span>save</span><span>(</span><span>follow_data</span><span>,</span><span> </span><span>file</span><span> </span><span>=</span><span> </span><span>&quot;follow_data.rda&quot;</span><span>)</span><span>
</span><span># number of calls left to make under Twitter's limits
</span><span> </span><span>lims</span><span> </span><span>&lt;-</span><span> </span><span>getCurRateLimitInfo</span><span>()</span><span>
</span><span>x</span><span> </span><span>&lt;-</span><span> </span><span>as.numeric</span><span>(</span><span>filter</span><span>(</span><span>lims</span><span>,</span><span> </span><span>resource</span><span> </span><span>==</span><span> </span><span>&quot;/followers/ids&quot;</span><span>)</span><span>$</span><span>remaining</span><span>)</span><span> </span><span>*</span><span>
</span><span>as.numeric</span><span>(</span><span>filter</span><span>(</span><span>lims</span><span>,</span><span> </span><span>resource</span><span> </span><span>==</span><span> </span><span>&quot;/friends/ids&quot;</span><span>)</span><span>$</span><span>remaining</span><span>)</span><span>
</span><span>while</span><span>(</span><span>x</span><span> </span><span>==</span><span> </span><span>0</span><span>)</span><span> </span><span>{</span><span>
</span><span>lims</span><span> </span><span>&lt;-</span><span> </span><span>getCurRateLimitInfo</span><span>()</span><span>
</span><span>x</span><span> </span><span>&lt;-</span><span> </span><span>as.numeric</span><span>(</span><span>filter</span><span>(</span><span>lims</span><span>,</span><span> </span><span>resource</span><span> </span><span>==</span><span> </span><span>&quot;/followers/ids&quot;</span><span>)</span><span>$</span><span>remaining</span><span>)</span><span> </span><span>*</span><span>
</span><span>as.numeric</span><span>(</span><span>filter</span><span>(</span><span>lims</span><span>,</span><span> </span><span>resource</span><span> </span><span>==</span><span> </span><span>&quot;/friends/ids&quot;</span><span>)</span><span>$</span><span>remaining</span><span>)</span><span>
</span><span>message</span><span>(</span><span>&quot;Waiting&quot;</span><span>)</span><span>
</span><span>Sys.sleep</span><span>(</span><span>60</span><span>)</span><span> </span><span># wait 15 minutes (or 1 minute, 15 times)
</span><span> </span><span>}</span><span>
</span><span>cat</span><span>(</span><span>paste</span><span>(</span><span>i</span><span>,</span><span> </span><span>current_sn</span><span>,</span><span> </span><span>&quot; | &quot;</span><span>))</span><span>
</span><span>current_user</span><span> </span><span>&lt;-</span><span> </span><span>getUser</span><span>(</span><span>current_sn</span><span>)</span><span>
</span><span>follow_data</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;screenName&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>current_sn</span><span>
</span><span># who this user follows (what happens if this is eg 1million people? I think it gets truncated at 75,000,
</span><span> </span><span># which is not as bad as it sounds as we only need a sample; but the problem will be that this is their
</span><span> </span><span># 75,000 most recent people they have followed, who might be biased to be newcomers?):
</span><span> </span><span># certain privacy settings stop you seeing someone's friends and followers, in which case
</span><span> </span><span># we try to sample another node from the last good person
</span><span> </span><span>all_my_friends</span><span> </span><span>&lt;-</span><span> </span><span>character</span><span>()</span><span>
</span><span>try</span><span>(</span><span>all_my_friends</span><span> </span><span>&lt;-</span><span> </span><span>current_user</span><span>$</span><span>getFriendIDs</span><span>())</span><span> </span><span># about 1 second for c.1500 IDs, longer for more
</span><span> </span><span>if</span><span>(</span><span>length</span><span>(</span><span>all_my_friends</span><span>)</span><span> </span><span>></span><span> </span><span>0</span><span>){</span><span>
</span><span># sample some of those friends
</span><span> </span><span>n</span><span> </span><span>&lt;-</span><span> </span><span>min</span><span>(</span><span>2000</span><span>,</span><span> </span><span>length</span><span>(</span><span>all_my_friends</span><span>))</span><span>
</span><span>sample_my_friends</span><span> </span><span>&lt;-</span><span> </span><span>sample</span><span>(</span><span>all_my_friends</span><span>,</span><span> </span><span>n</span><span>,</span><span> </span><span>replace</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>)</span><span>
</span><span>friend_details</span><span> </span><span>&lt;-</span><span> </span><span>lookupUsers</span><span>(</span><span>sample_my_friends</span><span>)</span><span> </span><span># about 15 seconds
</span><span> </span><span>friend_details_df</span><span> </span><span>&lt;-</span><span> </span><span>twListToDF</span><span>(</span><span>friend_details</span><span>)</span><span>
</span><span>follow_data</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;number_followers&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>current_user</span><span>$</span><span>followersCount</span><span>
</span><span>follow_data</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;number_following&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>current_user</span><span>$</span><span>friendsCount</span><span>
</span><span># mean number of followers of the people this user follows
</span><span> </span><span>follow_data</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;mean_ff&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>mean</span><span>(</span><span>friend_details_df</span><span>$</span><span>followersCount</span><span>)</span><span>
</span><span>follow_data</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;trmean_ff&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>mean</span><span>(</span><span>friend_details_df</span><span>$</span><span>followersCount</span><span>,</span><span> </span><span>tr</span><span> </span><span>=</span><span> </span><span>0.2</span><span>)</span><span>
</span><span>follow_data</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;median_ff&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>median</span><span>(</span><span>friend_details_df</span><span>$</span><span>followersCount</span><span>)</span><span>
</span><span>}</span><span>
</span><span># find the next user - flip a coin for it to be either a friend or a follower
</span><span> </span><span>current_sn</span><span> </span><span>&lt;-</span><span> </span><span>&quot;non_existent_user&quot;</span><span>
</span><span>while</span><span>(</span><span>current_sn</span><span> </span><span>==</span><span> </span><span>&quot;non_existent_user&quot;</span><span>){</span><span>
</span><span>if</span><span>(</span><span>sample</span><span>(</span><span>1</span><span>:</span><span>2</span><span>,</span><span> </span><span>1</span><span>)</span><span> </span><span>==</span><span> </span><span>1</span><span>){</span><span>
</span><span># 50% chance
</span><span> </span><span># pick one of the user's friends (ie people they follow) at random as the new node to sample
</span><span> </span><span># note that as a sampling strategy this will bias us towards people who are followed. People
</span><span> </span><span># who have few followers have little chance of being selected here. Does this matter?
</span><span> </span><span># Probably not for our main research question, but it does stop us doing meaningful inference
</span><span> </span><span># on population totals of number of people followed and number of people following - unless
</span><span> </span><span># we could estimate *how much* more likely people are to be followed, then we could estimate
</span><span> </span><span># weights to make up for it.
</span><span> </span><span>cat</span><span>(</span><span>&quot;\nsampling a friend\n&quot;</span><span>)</span><span>
</span><span>try</span><span>(</span><span>current_sn</span><span> </span><span>&lt;-</span><span> </span><span>sample_n</span><span>(</span><span>friend_details_df</span><span>,</span><span> </span><span>1</span><span>)</span><span>$</span><span>screenName</span><span>)</span><span>
</span><span>}</span><span> </span><span>else</span><span> </span><span>{</span><span>
</span><span># 50% chance
</span><span> </span><span># pick one of the user's followers as the new node. This is to mitigate the problem
</span><span> </span><span># noted above. We will still end up over-representing people with lots of followers
</span><span> </span><span># (who will be sampled by the previuos method), and people who follow lots of people
</span><span> </span><span># (more likely to be picked up in this alternative procedure in the next line), but
</span><span> </span><span># that is better than *only* over sampling people with lots of followers. Probably.
</span><span> </span><span>cat</span><span>(</span><span>&quot;\nsampling a follower\n&quot;</span><span>)</span><span>
</span><span># problem here when current_user has no followers:
</span><span> </span><span># a random sample from the last 1000 people to follow this person (ie biased to more </span><span> </span><span># recent, for people with lots of followers, but c'est la vie - important to speed things
</span><span> </span><span># up a bit)
</span><span> </span><span>try</span><span>(</span><span>follower_samp</span><span> </span><span>&lt;-</span><span> </span><span>sample</span><span>(</span><span>current_user</span><span>$</span><span>getFollowerIDs</span><span>(</span><span>n</span><span> </span><span>=</span><span> </span><span>1000</span><span>),</span><span> </span><span>1</span><span>))</span><span>
</span><span>try</span><span>(</span><span>current_sn</span><span> </span><span>&lt;-</span><span> </span><span>lookupUsers</span><span>(</span><span>follower_samp</span><span>)[[</span><span>1</span><span>]]</span><span>$</span><span>screenName</span><span>)</span><span>
</span><span>}</span><span>
</span><span>}</span><span>
</span><span>}</span></code></pre>
</figure>
<p>This gets me a sample that looks like the below. Note that this method is prone to sampling individuals more than once, particularly highly networked users (ie lots of followers and/or lots of people following). I’ll deal with that later by taking the average of the estimates of them.</p>
<figure>
<pre><code data-lang="r"><span>></span><span> </span><span>follow_data</span><span> </span><span>%>%</span><span>
</span><span>+</span><span> </span><span>arrange</span><span>(</span><span>desc</span><span>(</span><span>number_followers</span><span>))</span><span>
</span><span># A tibble: 983 x 6
</span><span> </span><span>number_followers</span><span> </span><span>number_following</span><span> </span><span>mean_ff</span><span> </span><span>trmean_ff</span><span> </span><span>median_ff</span><span> </span><span>screenName</span><span> </span><span></span><span>dbl</span><span>></span><span> </span><span></span><span>dbl</span><span>></span><span> </span><span></span><span>dbl</span><span>></span><span> </span><span></span><span>dbl</span><span>></span><span> </span><span></span><span>dbl</span><span>></span><span> </span><span></span><span>chr</span><span>></span><span> </span><span>1</span><span> </span><span>108538969</span><span> </span><span>203</span><span> </span><span>6002702</span><span> </span><span>1227629</span><span> </span><span>450295</span><span> </span><span>katyperry</span><span> </span><span>2</span><span> </span><span>71131344</span><span> </span><span>1034</span><span> </span><span>3113456</span><span> </span><span>373193</span><span> </span><span>140602</span><span> </span><span>YouTube</span><span> </span><span>3</span><span> </span><span>44212387</span><span> </span><span>183</span><span> </span><span>3208975</span><span> </span><span>594062</span><span> </span><span>255161</span><span> </span><span>BillGates</span><span> </span><span>4</span><span> </span><span>40436829</span><span> </span><span>1868</span><span> </span><span>810532</span><span> </span><span>38519</span><span> </span><span>17959</span><span> </span><span>narendramodi</span><span> </span><span>5</span><span> </span><span>40410386</span><span> </span><span>1867</span><span> </span><span>810495</span><span> </span><span>38519</span><span> </span><span>17926</span><span> </span><span>narendramodi</span><span> </span><span>6</span><span> </span><span>40409932</span><span> </span><span>1867</span><span> </span><span>810489</span><span> </span><span>38519</span><span> </span><span>17926</span><span> </span><span>narendramodi</span><span> </span><span>7</span><span> </span><span>40400380</span><span> </span><span>1868</span><span> </span><span>809897</span><span> </span><span>38479</span><span> </span><span>17924</span><span> </span><span>narendramodi</span><span> </span><span>8</span><span> </span><span>35470473</span><span> </span><span>1661</span><span> </span><span>1559447</span><span> </span><span>334577</span><span> </span><span>219023</span><span> </span><span>SportsCenter</span><span> </span><span>9</span><span> </span><span>24954373</span><span> </span><span>424</span><span> </span><span>1182455</span><span> </span><span>232537</span><span> </span><span>96970</span><span> </span><span>PMOIndia</span><span> </span><span>10</span><span> </span><span>21680806</span><span> </span><span>771</span><span> </span><span>900960</span><span> </span><span>6736</span><span> </span><span>2814</span><span> </span><span>HillaryClinton</span><span>
</span><span>#</span><span> </span><span>...</span><span> </span><span>with</span><span> </span><span>973</span><span> </span><span>more</span><span> </span><span>rows</span></code></pre>
</figure>
<p>The snapshot sampling method is a bit simpler. All I need is 1,000 random tweets, which I get by searching for tweets containing the letter “e” (as <code>twitteR</code> doesn’t facilitate a completely open search as far as I can see). This isn’t great – I think it eliminates people using some character sets – but is good enough for a blog.</p>
<figure>
<pre><code data-lang="r"><span>#==================snapshot sampling method===========
# The first method of sampling will oversample people with lots of followers and people
# with lots of friends. As this is potentially linked to the response variable (indirectly)
# it might be better to try an alternative sampling method, by grabbing a bunch of tweets.
# This method will oversample people who are active tweeting today, which is a different
# sort of coverage problem, so still need to be careful.
</span><span>follow_data_2</span><span> </span><span>&lt;-</span><span> </span><span>data_frame</span><span>(</span><span>
</span><span>number_followers</span><span> </span><span>=</span><span> </span><span>integer</span><span>(),</span><span>
</span><span>number_following</span><span> </span><span>=</span><span> </span><span>integer</span><span>(),</span><span>
</span><span>mean_ff</span><span> </span><span>=</span><span> </span><span>numeric</span><span>(),</span><span>
</span><span>trmean_ff</span><span> </span><span>=</span><span> </span><span>numeric</span><span>(),</span><span>
</span><span>median_ff</span><span> </span><span>=</span><span> </span><span>numeric</span><span>(),</span><span>
</span><span>screenName</span><span> </span><span>=</span><span> </span><span>character</span><span>()</span><span>
</span><span>)</span><span>
</span><span># 1000 random tweets with the letter &quot;e&quot; in them:
</span><span>tweets</span><span> </span><span>&lt;-</span><span> </span><span>searchTwitter</span><span>(</span><span>&quot;e&quot;</span><span>,</span><span> </span><span>n</span><span> </span><span>=</span><span> </span><span>1000</span><span>)</span><span>
</span><span># the users
</span><span>users</span><span> </span><span>&lt;-</span><span> </span><span>unique</span><span>(</span><span>sapply</span><span>(</span><span>tweets</span><span>,</span><span> </span><span>function</span><span>(</span><span>x</span><span>){</span><span>x</span><span>$</span><span>screenName</span><span>}))</span><span>
</span><span>for</span><span>(</span><span>i</span><span> </span><span>in</span><span> </span><span>1</span><span>:</span><span>length</span><span>(</span><span>users</span><span>)){</span><span>
</span><span># save latest copy of results in case of crash
</span><span> </span><span>save</span><span>(</span><span>follow_data_2</span><span>,</span><span> </span><span>file</span><span> </span><span>=</span><span> </span><span>&quot;follow_data_2.rda&quot;</span><span>)</span><span>
</span><span># number of calls left to make under Twitter's limits
</span><span> </span><span>lims</span><span> </span><span>&lt;-</span><span> </span><span>getCurRateLimitInfo</span><span>()</span><span>
</span><span>x</span><span> </span><span>&lt;-</span><span> </span><span>as.numeric</span><span>(</span><span>filter</span><span>(</span><span>lims</span><span>,</span><span> </span><span>resource</span><span> </span><span>==</span><span> </span><span>&quot;/followers/ids&quot;</span><span>)</span><span>$</span><span>remaining</span><span>)</span><span> </span><span>*</span><span>
</span><span>as.numeric</span><span>(</span><span>filter</span><span>(</span><span>lims</span><span>,</span><span> </span><span>resource</span><span> </span><span>==</span><span> </span><span>&quot;/friends/ids&quot;</span><span>)</span><span>$</span><span>remaining</span><span>)</span><span>
</span><span>while</span><span>(</span><span>x</span><span> </span><span>==</span><span> </span><span>0</span><span>)</span><span> </span><span>{</span><span>
</span><span>lims</span><span> </span><span>&lt;-</span><span> </span><span>getCurRateLimitInfo</span><span>()</span><span>
</span><span>x</span><span> </span><span>&lt;-</span><span> </span><span>as.numeric</span><span>(</span><span>filter</span><span>(</span><span>lims</span><span>,</span><span> </span><span>resource</span><span> </span><span>==</span><span> </span><span>&quot;/followers/ids&quot;</span><span>)</span><span>$</span><span>remaining</span><span>)</span><span> </span><span>*</span><span>
</span><span>as.numeric</span><span>(</span><span>filter</span><span>(</span><span>lims</span><span>,</span><span> </span><span>resource</span><span> </span><span>==</span><span> </span><span>&quot;/friends/ids&quot;</span><span>)</span><span>$</span><span>remaining</span><span>)</span><span>
</span><span>message</span><span>(</span><span>&quot;Waiting&quot;</span><span>)</span><span>
</span><span>Sys.sleep</span><span>(</span><span>60</span><span>)</span><span> </span><span># wait 15 minutes (or 1 minute, 15 times)
</span><span> </span><span>}</span><span>
</span><span>current_sn</span><span> </span><span>&lt;-</span><span> </span><span>users</span><span>[</span><span>i</span><span>]</span><span>
</span><span>cat</span><span>(</span><span>paste</span><span>(</span><span>i</span><span>,</span><span> </span><span>current_sn</span><span>,</span><span> </span><span>&quot; | &quot;</span><span>))</span><span>
</span><span>try</span><span>({</span><span>
</span><span>current_user</span><span> </span><span>&lt;-</span><span> </span><span>getUser</span><span>(</span><span>current_sn</span><span>)</span><span> </span><span># this fails surprisingly often, not sure why
</span><span> </span><span>follow_data_2</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;screenName&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>current_sn</span><span>
</span><span># who this user follows (what happens if this is eg 1million people? I think it gets truncated at 15,000,
</span><span> </span><span># which is not as bad as it sounds as we only need a sample; but the problem will be that this is their
</span><span> </span><span># 15,000 most recent people they have followed, who might be biased to be newcomers?):
</span><span> </span><span># certain privacy settings stop you seeing someone's friends and followers, in which case
</span><span> </span><span># we try to sample another node from the last good person
</span><span> </span><span>all_my_friends</span><span> </span><span>&lt;-</span><span> </span><span>character</span><span>()</span><span>
</span><span>try</span><span>(</span><span>all_my_friends</span><span> </span><span>&lt;-</span><span> </span><span>current_user</span><span>$</span><span>getFriendIDs</span><span>())</span><span> </span><span># about 1 second for c.1500 IDs, longer for more
</span><span> </span><span>if</span><span>(</span><span>length</span><span>(</span><span>all_my_friends</span><span>)</span><span> </span><span>></span><span> </span><span>0</span><span>){</span><span>
</span><span># sample some of those friends
</span><span> </span><span>n</span><span> </span><span>&lt;-</span><span> </span><span>min</span><span>(</span><span>2000</span><span>,</span><span> </span><span>length</span><span>(</span><span>all_my_friends</span><span>))</span><span>
</span><span>sample_my_friends</span><span> </span><span>&lt;-</span><span> </span><span>sample</span><span>(</span><span>all_my_friends</span><span>,</span><span> </span><span>n</span><span>,</span><span> </span><span>replace</span><span> </span><span>=</span><span> </span><span>FALSE</span><span>)</span><span>
</span><span>friend_details</span><span> </span><span>&lt;-</span><span> </span><span>lookupUsers</span><span>(</span><span>sample_my_friends</span><span>)</span><span> </span><span># about 15 seconds
</span><span> </span><span>friend_details_df</span><span> </span><span>&lt;-</span><span> </span><span>twListToDF</span><span>(</span><span>friend_details</span><span>)</span><span>
</span><span>follow_data_2</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;number_followers&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>current_user</span><span>$</span><span>followersCount</span><span>
</span><span>follow_data_2</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;number_following&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>current_user</span><span>$</span><span>friendsCount</span><span>
</span><span># mean number of followers of the people this user follows
</span><span> </span><span>follow_data_2</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;mean_ff&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>mean</span><span>(</span><span>friend_details_df</span><span>$</span><span>followersCount</span><span>)</span><span>
</span><span>follow_data_2</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;trmean_ff&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>mean</span><span>(</span><span>friend_details_df</span><span>$</span><span>followersCount</span><span>,</span><span> </span><span>tr</span><span> </span><span>=</span><span> </span><span>0.2</span><span>)</span><span>
</span><span>follow_data_2</span><span>[</span><span>i</span><span>,</span><span> </span><span>&quot;median_ff&quot;</span><span>]</span><span> </span><span>&lt;-</span><span> </span><span>median</span><span>(</span><span>friend_details_df</span><span>$</span><span>followersCount</span><span>)</span><span>
</span><span>}</span><span>
</span><span>})</span><span>
</span><span>}</span></code></pre>
</figure>
<h2>Results</h2>
<p>The resulting numbers are all very skewed distributions. Visually, they look good when you take the logarithm of the original number plus 1 (needed to avoid turning people with 0 friends or 0 followers becoming <code>-Inf</code>). I can justify “+ 1” by saying that, in a way, everyone follows themself and is followed by themselves.</p>
<p>Here’s the distributions and relationships of the key variables, when transformed this way:</p>
<p><img src="https://i0.wp.com/ellisp.github.io/img/0118-pairs.png?w=100%25" data-recalc-dims="1"></p>
<p>We see a strong positive relationship between number of your followers and number of people you are following – until we get to people with many followers (10,000 or more), when the relationship breaks down (visible only in the snowball sample, as the simpler “today’s tweeters” sampling method harvests few such people). Partly this comes from reciprocal follow-back arrangements, partly it is a general indicator of longevity.</p>
<p>We also see a strongly negative relationship between number of people one is following and the average number of their followers. This makes sense and fits in with the notion that if you want to be following people with lots of followers, you have to be quite selective in who you follow, and its best to follow big names in sport, entertainment and perhaps politics. Consider Trump supporter <a rel="nofollow" href="https://twitter.com/TheRoyalPosts" target="_blank">@TheRoyalPosts</a> as an extreme example (not actually included in the final sample). With 41,700 followers of her own, she follows only 120 prominent political accounts, with an astonishing average number of followers themselves of 7 million.</p>
<p>At this point let’s have another look at the graphic I started the post with:</p>
<p><img width="100%" src="http://ellisp.github.io/img/0118-main-scatter.svg"></p>
<p>From these last couple of charts, I’m actually pretty happy with both of my sampling methods.</p>
<p>Here’s the code that combines the two samples and produces the graphics above.</p>
<figure>
<pre><code data-lang="r"><span>#==================analysis========================
</span><span>
</span><span>follow_data_proc</span><span> </span><span>&lt;-</span><span> </span><span>follow_data</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>sampling_method</span><span> </span><span>=</span><span> </span><span>&quot;Snowball sampling\nalong network&quot;</span><span>)</span><span>
</span><span>follow_data_proc_2</span><span> </span><span>&lt;-</span><span> </span><span>follow_data_2</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>sampling_method</span><span> </span><span>=</span><span> </span><span>&quot;Sample of today's tweeters&quot;</span><span>)</span><span> </span><span>follow_data_comb</span><span> </span><span>&lt;-</span><span> </span><span>rbind</span><span>(</span><span>follow_data_proc</span><span>,</span><span> </span><span>follow_data_proc_2</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>filter</span><span>(</span><span>!</span><span>is.na</span><span>(</span><span>trmean_ff</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>group_by</span><span>(</span><span>screenName</span><span>,</span><span> </span><span>sampling_method</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>summarise</span><span>(</span><span>
</span><span>number_followers</span><span> </span><span>=</span><span> </span><span>mean</span><span>(</span><span>number_followers</span><span>),</span><span>
</span><span>number_following</span><span> </span><span>=</span><span> </span><span>mean</span><span>(</span><span>number_following</span><span>),</span><span>
</span><span>mean_ff</span><span> </span><span>=</span><span> </span><span>mean</span><span>(</span><span>mean_ff</span><span>),</span><span>
</span><span>trmean_ff</span><span> </span><span>=</span><span> </span><span>mean</span><span>(</span><span>trmean_ff</span><span>),</span><span>
</span><span>median_ff</span><span> </span><span>=</span><span> </span><span>mean</span><span>(</span><span>median_ff</span><span>),</span><span>
</span><span>n_obs</span><span> </span><span>=</span><span> </span><span>n</span><span>()</span><span>
</span><span>)</span><span> </span><span>%>%</span><span>
</span><span>ungroup</span><span>()</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>many_following</span><span> </span><span>=</span><span> </span><span>cut</span><span>(</span><span>number_following</span><span>,</span><span> </span><span>breaks</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>0</span><span>,</span><span> </span><span>1000</span><span>,</span><span> </span><span>5000</span><span>,</span><span> </span><span>15000</span><span>,</span><span> </span><span>75000</span><span>,</span><span> </span><span>10</span><span> </span><span>^</span><span> </span><span>9</span><span>),</span><span>
</span><span>labels</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;0 - 1,000&quot;</span><span>,</span><span> </span><span>&quot;1,001 - 5,000&quot;</span><span>,</span><span> </span><span>&quot;5,001 - 15,000&quot;</span><span>,</span><span> </span><span>&quot;15,001 - 75,000&quot;</span><span>,</span><span> </span><span>&quot;75,001 or more&quot;</span><span>)))</span><span>
</span><span>follow_data_trans</span><span> </span><span>&lt;-</span><span> </span><span>follow_data_comb</span><span> </span><span>%>%</span><span>
</span><span>mutate</span><span>(</span><span>number_followers_l</span><span> </span><span>=</span><span> </span><span>log10</span><span>(</span><span>number_followers</span><span> </span><span>+</span><span> </span><span>1</span><span>),</span><span>
</span><span>number_following_l</span><span> </span><span>=</span><span> </span><span>log10</span><span>(</span><span>number_following</span><span> </span><span>+</span><span> </span><span>1</span><span>),</span><span>
</span><span>trmean_ff_l</span><span> </span><span>=</span><span> </span><span>log10</span><span>(</span><span>trmean_ff</span><span> </span><span>+</span><span> </span><span>1</span><span>))</span><span> </span><span>%>%</span><span>
</span><span>select</span><span>(</span><span>number_followers_l</span><span>,</span><span> </span><span>number_following_l</span><span>,</span><span> </span><span>trmean_ff_l</span><span>,</span><span> </span><span>sampling_method</span><span>)</span><span> </span><span>ggpairs</span><span>(</span><span>follow_data_trans</span><span>,</span><span> </span><span>columns</span><span> </span><span>=</span><span> </span><span>1</span><span>:</span><span>3</span><span>,</span><span> </span><span>mapping</span><span> </span><span>=</span><span> </span><span>aes</span><span>(</span><span>colour</span><span> </span><span>=</span><span> </span><span>sampling_method</span><span>))</span><span>
</span><span>ggplot</span><span>(</span><span>follow_data_comb</span><span>,</span><span> </span><span>aes</span><span>(</span><span>x</span><span> </span><span>=</span><span> </span><span>number_followers</span><span>,</span><span> </span><span>y</span><span> </span><span>=</span><span> </span><span>trmean_ff</span><span>))</span><span> </span><span>+</span><span> </span><span>facet_wrap</span><span>(</span><span>~</span><span>sampling_method</span><span>)</span><span> </span><span>+</span><span>
</span><span>geom_point</span><span>(</span><span>aes</span><span>(</span><span>fill</span><span> </span><span>=</span><span> </span><span>many_following</span><span>),</span><span> </span><span>pch</span><span> </span><span>=</span><span> </span><span>21</span><span>)</span><span> </span><span>+</span><span>
</span><span>geom_smooth</span><span>(</span><span>method</span><span> </span><span>=</span><span> </span><span>&quot;loess&quot;</span><span>)</span><span> </span><span>+</span><span>
</span><span>scale_x_log10</span><span>(</span><span>&quot;Number of followers, of this person&quot;</span><span>,</span><span> </span><span>label</span><span> </span><span>=</span><span> </span><span>comma</span><span>)</span><span> </span><span>+</span><span>
</span><span>scale_y_log10</span><span>(</span><span>&quot;Trimmed mean number of followers,\nof the people this person follows&quot;</span><span>,</span><span> </span><span>label</span><span> </span><span>=</span><span> </span><span>comma</span><span>)</span><span> </span><span>+</span><span>
</span><span>ggtitle</span><span>(</span><span>&quot;Do people with more followers follow people with more followers?&quot;</span><span>,</span><span>
</span><span>&quot;Apparently 'it depends'.&quot;</span><span>)</span><span> </span><span>+</span><span>
</span><span>scale_fill_brewer</span><span>(</span><span>&quot;Following how\nmany people:&quot;</span><span>,</span><span> </span><span>palette</span><span> </span><span>=</span><span> </span><span>&quot;Spectral&quot;</span><span>,</span><span>
</span><span>guide</span><span> </span><span>=</span><span> </span><span>guide_legend</span><span>(</span><span>title.hjust</span><span> </span><span>=</span><span> </span><span>0.5</span><span>,</span><span> </span><span>override.aes</span><span> </span><span>=</span><span> </span><span>list</span><span>(</span><span>size</span><span> </span><span>=</span><span> </span><span>5</span><span>)))</span><span> </span><span>+</span><span>
</span><span>theme</span><span>(</span><span>legend.position</span><span> </span><span>=</span><span> </span><span>&quot;right&quot;</span><span>)</span></code></pre>
</figure>
<h2>Modelling</h2>
<p>Finally, I wanted to see if the apparent u-shaped relationship between number of followers and the average number of followers of people one follows was robust to a model that simultaneously modelled the strongly negative relationship between the number of people one follows and that same response variable. It turns out that this is the case. Here are the partial effects of the two variables in a generalized additive model without an interaction term:</p>
<p><img width="100%" src="http://ellisp.github.io/img/0118-simple.svg"></p>
<p>And here is how the relationship looks when there is an interaction term. First, as a three-dimensional perspective plot:</p>
<p><img width="100%" src="http://ellisp.github.io/img/0118-persp.svg"></p>
<p>… then, more usefully as a heatmap.</p>
<p><img width="100%" src="http://ellisp.github.io/img/0118-heatmap.svg"></p>
<p>The interaction is significant so we’d keep it in even though it complicates the interpretation.</p>
<p>I think the heatmap is the best representation of the data. It shows clearly that the average number of followers of the people one follows is:</p>
<ul>
<li>high for people with few followers</li>
<li>high for people with many followers who <em>don’t</em> follow many themselves</li>
<li>low for people with many followers who <em>do</em> follow lots of people themselves</li>
</ul>
<p>Additionally, there are are very few or no users who follow hundreds of thousands of accounts but have a low number of their own followers (hence the white space in the top left corner).</p>
<p>Here’s the code for the modelling:</p>
<figure>
<pre><code data-lang="r"><span>mod_full</span><span> </span><span>&lt;-</span><span> </span><span>gam</span><span>(</span><span>trmean_ff_l</span><span> </span><span>~</span><span> </span><span>s</span><span>(</span><span>number_followers_l</span><span>,</span><span> </span><span>number_following_l</span><span>),</span><span> </span><span>data</span><span> </span><span>=</span><span> </span><span>follow_data_trans</span><span>)</span><span>
</span><span>mod_simp</span><span> </span><span>&lt;-</span><span> </span><span>gam</span><span>(</span><span>trmean_ff_l</span><span> </span><span>~</span><span> </span><span>s</span><span>(</span><span>number_followers_l</span><span>)</span><span> </span><span>+</span><span> </span><span>s</span><span>(</span><span>number_following_l</span><span>),</span><span> </span><span>data</span><span> </span><span>=</span><span> </span><span>follow_data_trans</span><span>)</span><span>
</span><span>anova</span><span>(</span><span>mod_full</span><span>,</span><span> </span><span>mod_simp</span><span>,</span><span> </span><span>test</span><span> </span><span>=</span><span> </span><span>&quot;F&quot;</span><span>)</span><span>
</span><span># simple two variable model
</span><span>par</span><span>(</span><span>bty</span><span> </span><span>=</span><span> </span><span>&quot;l&quot;</span><span>,</span><span> </span><span>font.main</span><span> </span><span>=</span><span> </span><span>1</span><span>)</span><span>
</span><span>plot</span><span>(</span><span>mod_simp</span><span>,</span><span> </span><span>pages</span><span> </span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>main</span><span> </span><span>=</span><span> </span><span>&quot;No-interaction model&quot;</span><span>)</span><span> </span><span># perspective plot
</span><span>plot</span><span>(</span><span>mod_full</span><span>,</span><span> </span><span>pages</span><span> </span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>scheme</span><span> </span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>main</span><span> </span><span>=</span><span> </span><span>(</span><span>&quot;Impact on the trimmed mean number\nof followers of people that are followed&quot;</span><span>))</span><span>
</span><span># heat map
</span><span>plot</span><span>(</span><span>mod_full</span><span>,</span><span> </span><span>pages</span><span> </span><span>=</span><span> </span><span>1</span><span>,</span><span> </span><span>scheme</span><span> </span><span>=</span><span> </span><span>2</span><span>,</span><span> </span><span>hcolors</span><span> </span><span>=</span><span> </span><span>topo.colors</span><span>(</span><span>50</span><span>),</span><span>
</span><span>main</span><span> </span><span>=</span><span> </span><span>(</span><span>&quot;Impact on the trimmed mean number\nof followers of people that are followed&quot;</span><span>),</span><span>
</span><span>xlab</span><span> </span><span>=</span><span> </span><span>&quot;Logarithm of number of followers&quot;</span><span>,</span><span>
</span><span>ylab</span><span> </span><span>=</span><span> </span><span>&quot;Logarithm of number people following&quot;</span><span>)</span><span>
</span><span>legend</span><span>(</span><span>&quot;topleft&quot;</span><span>,</span><span> </span><span>legend</span><span> </span><span>=</span><span> </span><span>c</span><span>(</span><span>&quot;low&quot;</span><span>,</span><span> </span><span>&quot;medium&quot;</span><span>,</span><span> </span><span>&quot;high&quot;</span><span>),</span><span> </span><span>fill</span><span> </span><span>=</span><span> </span><span>topo.colors</span><span>(</span><span>3</span><span>),</span><span> </span><span>bty</span><span> </span><span>=</span><span> </span><span>&quot;n&quot;</span><span>,</span><span> </span><span>cex</span><span> </span><span>=</span><span> </span><span>1.2</span><span>)</span></code></pre>
</figure>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://ellisp.github.io/blog/2018/02/24/following-followers"> Peter's stats stuff - R</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/W7c69ZddwYc" height="1"></a></div>