text:
Three Things We Learned Wednesday: Kevin Durant saves his best games for Thunder
Here are the big takeaways from a busy night around the NBA:
1) Kevin Durant saves his best games for Russell Westbrook, Thunder. Prior to Wednesday night, Kevin Durant's highest-scoring game this season was 39 points, something he broke out the first time his new Warriors team faced his old Thunder squad. Then Wednesday Durant an incredibly efficient 40 points on 16 shots — again against the Thunder. Just in case there wasn't enough salt rubbed in that OKC wound (Golden State won the game 121-100).
Whatever you think of his choice, Durant's team is way better than Westbrook's, which is both expected and why KD made the move — he is closer to a ring now. (If you say that winning rings is the ultimate defining factor in a player's legacy then rip his moves to make it easier to get said ring, you're a hypocrite.) Part of the gap between the sides is obviously what Durant brings to the Golden State offense — and how efficiently he's been doing it this season, with a true shooting percentage of 65.9, his career best (for some perspective, the league average is around 52). But also he's been bringing it on the defensive end this season, particularly of late, having a strong game against LeBron James Monday then doing well when switched onto Westbrook a couple of times in this game. Durant would be having an MVP-level season most years, but Westbrook and James Harden change the equation this time around.
Westbrook himself had a triple-double (that's 21 this season) in the loss... actually, it was a quadruple-double when you throw in the 10 turnovers. Westbrook wasn't efficient, hitting 8-of-23 from the field, and when he isn't this team struggles to win, they rely on him that much. Of course, that's not the play everyone is talking about — rather, it's Zaza Pachulia with the hard foul, and then taunting Westbrook by standing over him.
When Westbrook saw that, he promised to "get his ass back." These teams meet again Feb. 11 — when Durant returns to Oklahoma City for the first time in a Warriors' uniform.
Bonus thing we saw: Russell Westbrook had the travel of the year. Even in the NBA, this is a travel — and a funny one.
2) The Sixers beat the Raptors and have now won 7-of-9. When this run of wins from the Sixers started, it was easy to say "they are just beating other weak teams." Then they beat the Bucks. Wednesday night they beat the Raptors. Brett Brown has settled on a 10-man rotation, found lineups he likes with Joel Embiid starting (surrounded by shooters) and Nerlens Noel relieving him off the bench. Plus, the Sixers are finding their defensive identity. It's coming together.
Still, this is all about Embiid — the Sixers are outscoring teams by 3.5 points per 100 possessions when he is on the court this season. He had 26 points — including 12-of-14 from the free throw line — plus nine rebounds against Toronto. The man is a force. The only question the next couple of weeks is will he be an All-Star?
3) Rudy Gay is out for the season, which changes West playoff chase and trade picture. This is bad news for the Kings, and it is worse news for Rudy Gay himself — trying to drive out of the right corner Wednesday night, Gay tore his left Achilles tendon (something the team announced, although it needs to be confirmed by an MRI Thursday).
Gay is done for this season and likely the start of the next one.
In the short term, that is a blow to the Kings' playoff chances. Technically they are just 1.5 games out of the eight seed after Wednesday's loss to the Pacers, but the Kings have been outscored by 10 points per 100 possessions this season when Gay is off the court. This isn't the same team without him. Gay has scored 18.7 points per game, which was second-best on the team, and now that role falls to Matt Barnes and Omri Casspi (once Casspi returns from his calf injury in a couple of weeks). Those two are a drop off from what Gay brought to the Kings, meaning don't be surprised if Sacramento tries to add a scorer at the trade deadline.
It also changes the trade deadline. Gay was clear he wanted out of Sacramento and said he planned to opt out of the $14.3 million final year of his contract to be a free agent next summer, which made him someone on the trade block. Teams were calling about him, including the Thunder (although the Kings being in the playoff hunt impacted what the team might do). Now obviously that is off the table, and the question becomes will Gay even opt out?


text:
Chris Hastings: What is New York Cuisine?
JBF EditorsJBF Editors
June 26, 2013
For the New York issue of our member newsletter, JBF Notes, we asked past Best Chef award winners from regions around the country to tell us what cuisine in the Big Apple means to them, and, of course, for their must-visit spots when they're in town. We'll be posting their responses throughout the week. Next up: Chris Hastings, winner of the 2012 Best Chef: South award and chef of Hot and Hot Fish Club in Birmingham, Alabama.
What is New York cuisine?
For me, New York City is a place I go to experience the best food this country has to offer on all levels, from small hole-in-the-wall neighborhood spots that have been around for years to the finest restaurants in the country and everything in between. I usually go for work with a side of enjoyment, but my visits are guaranteed to refresh ideas and ignite inspiration.
Favorite restaurants?
Il Buco is always spot on in terms of flavor and technique. The atmosphere is one of my favorites and there's always a great meal to be had. Roberta's in Brooklyn—part of the experience is just getting there. There's a whole new life inside, behind that door. We also love the Dutch and anything Andrew Carmellini does. We have been hearing great things about what Kyle Knall is doing at Maysville and are looking forward to making a stop there on my next trip. My wife and I make it a point to sit at the bar at Union Square Café for drinks and dinner. That's just a timeless spot for us.

subset: commoncrawl


text:
Moving into UD off-campus apartments or other housing can be stressful. At UDelHousing, LLC we want to make sure the whole rental process goes smoothly. After you secured your housing, you still will need to make sure your utilities (electric, gas, water, trash, internet, and TV) will be ready to go when you move in.
Links for Moving Into UD Off-Campus Apartments or Housing
The University of Delaware has various maps online that includes an index of buildings and special keys denoting the University Visitors Center and visitor parking, as well as dining facilities, residence halls, UD Bookstore locations, restrooms, public telephones, and the city's municipal parking lots.
City of Newark Electric Utilities
A refundable deposit is required to open an electric account. For information on connection/disconnection of service, billing questions, or customer service inquiries, you may call Utility Billing at (302) 366-7085 between 8:30 a.m. and 5:00 p.m.
To report a power outage or emergency involving electric services, call 366-7050 from 8:30 a.m. to 5:00 p.m. on weekdays. On weekends or holidays, or after 5:00 p.m. on weekdays, call 366-7000 to report electric service emergencies.
Refuse collection services are provided twice weekly at no cost to Newark residents. Refuse should be placed curbside in watertight, 20-30 gallon bags or containers with lids and handles by 7:00 a.m. on the morning of collection. The maximum weight of bags or containers should not exceed 40 pounds. For further information, please call 366-7045.
City of Newark Water Utilities
For information on connection/disconnection of service, billing questions, or customer service inquiries, you may call Utility Billing at (302) 366-7085 between 8:30 a.m. and 5:00 p.m. For water service problems first confirm that it is from the city's supply, and not coming from your hot water heater. If it is the city's supply, call the department at 366-7055, and report it.
If you have an immediate service need, please contact Delmarva Customer Service Center. In Delaware, Maryland, and Virginia, call 1-800-375-7117. Delmarva Customer Care Representatives are available Monday – Friday 7AM to 7PM; excluding major holidays.
You may contact Comcast by calling 1-800-COMCAST or using the online Customer Support.
You may contact Verizon by online Customer Support.


text:
Main Club Facility 181 Colfax Ave.
Clifton , N.J. 07013
Administration Offices/Mailing Address 822 Clifton Ave
Clifton , N.J. 07013
Your contributions can help us provide the guidance our youth needs.
The Pre – Teen / Teen program provides members ages 11–15 opportunities designed to help build character, career development, community and civic involvement and aides in the development of social and life skills.
Boys and Girls Club of Clifton. All Rights Reserved.
Website Designed by
Hudson Horizons
Download our new App:


text:
If you're looking for a market with smartphone sales growth potential then India usually comes to mind, but the market is moving forward with much promise in Indonesia, the world's fourth largest country.
A new report from IDC shows that smartphones sales in the country accelerated by 13 percent year-on-year during the first quarter of 2017. A total of 7.3 million devices shipped were shipped during the period in Indonesia, which has a population of 263 million.
While that's some ways behind India on raw figures — IDC estimates that 27 million phones were shipped in India in Q1 — it is close to India's annual growth (14.8 percent) and it is still considerably above the global smartphone sales growth rate of 4.3 percent.
Indonesia has a lot in common with India in that phone sales are being shaped by aggressive Chinese brands entering the country. IDC found that Chinese companies accounted for 31 percent of the marketshare, up from 23 percent a year ago and 12 percent two years ago.
Global companies, most prominently Samsung, hold a dominant 47 percent share, but that's down from more than 50 percent one year ago.
In order, Samsung ranked top ahead of Chinese duo Oppo and Asus, with local brand Advan and Lenovo-Motorola rounding out the top five.
"The smartphone market in Indonesia as we know it has changed with the China-based vendors becoming more aggressive with their strategies, not just with their product line-up but also their overall marketing plans and activities," IDC analyst Risky Febrian said in a statement.
"Their cash-rich initiatives have left local vendors struggling to compete in the market space with their limited resources. Meanwhile Samsung has revamped its strategy to fend off the competition and maintain market leadership," Febrian added.
Indeed, the rest of Southeast Asia has seen a similar Chinese invasion. Oppo and Vivo, in particular, have posted gains which, when combined with huge success at home in China, has vaulted them into the world's top five smartphone sellers.
This is just the start for Indonesia, and there's likely to be increased competition going forward.
IDC predicts that the entry of newly franchised BlackBerry smartphones — the Canadian brand remains popular in Indonesia thanks to widespread adoption of its BBM messenger — Xiaomi's fresh line-up and Nokia, another old favorite being re-energized by HMD, will put even more pressure on the market, particularly for local brands.


text:
By Sebastian Godinez,
Before I write anything further: Trigger alert. A few years ago, I wrote a series of articles on the freedom of speech. However, beyond mentioning that to ban phrases such as "motherhood" and "American," (both of which are absolutely unconstitutional, not to mention questionable as to why they need to be banned in the first place), I have only hardened my belief that we need to protect and exercise this right. And herein lies my point.
Liberals are actively engaging in the suppression of free speech. They do this in a myriad of ways. First is the way mentioned above: banning certain words. Second, they do not, with few exceptions, invite speakers with a diverse set of political views. If you need an example, the UC system tried to invite Ann Coulter, a controversial conservative talking head, to give a speech. What did students and faculty do? Shut it down. So much for freedom of speech. And, perhaps, the most inadvertent way they do it is simply shutting someone down or calling someone who holds a sincere belief contrary to theirs, particularly on controversial issues of race, gender and politics, "bigot," "racist," "sexist," etc. We all have done it, yours truly as well. The problem with doing that is two-fold. First, it's rude, not to mention, infringing on that person's right to that belief and to express it as such. Second, it creates an echo chamber. How many of us actively read things, whether it's on Facebook, newsletters or print, that oppose our own views? I may be wrong, but I doubt it's many of us. I'm not claiming to be immune from this myself either. I still trend towards certain news sources. But I'm more open to hearing criticisms and opposing views than many people my own age or older.
I also want to address a somewhat, but not necessarily related, issue I have with liberals. Many liberals are socially progressive and advocate for gender equality. And largely, I'm in step with them. I too want equal pay, equal representation in government and the end of sexual harassment in the workplace and everywhere else. But there are, and this is my conservative upbringing speaking, specific ways that we have to refer to men and women. It's perfectly fine to call a man a fat if he's overweight, but I was always told that's a rude thing to say to women. Ditto for asking a woman her weight and height. Of course, there are perfectly legitimate privacy concerns, but those aside, why is it not rude for men but is for women? I could address the same issue related to race, such as why it's totally fine to call white people "crackers" and "white trash," but when reversed its racist. But I think I've largely made my point and I have to be within a word limit. If you'd like to respond and explain these things to me (maybe I'm totally wrong), send me an email? But please keep it civil.
Sebastian is a senior Political Science major.
Graphic by David Giacomini.


text:
Heart Ring | Heart Shape Ring | Heart Ring Diamond
Heart Ring Diamond | Heart Ring
Minx London presents this beautiful Heart Ring , this cubic zirconia ring has the look and feel of a real heart shaped diamond ring. So wether you desire a Fashion Ring, or an Eternity Ring, this Heart Shape Ring will give you the shine of a Goddess!
Heart Shape Ring
Minx London Heart ring is crafted as an extremely high quality Cubic Zirconia Ring, often using 6A cubic zirconia ring stones which is the highest standard.
The sparkle created is so dazzling that even experts would need to examine heavily to confirm wether it is a genuine heart shaped diamond ring or simply a heart shaped ring made of cubic zirconia.
Heart Shaped Diamond Ring
Unbeknown to many is that celebrities, social media influencers etc... often wear such heart rings & iced out rings that is manufactured by the same artisans that we design with and source our heart shaped rings and other heart shaped Diamond Ring jewellery from.
Since photos don not always captivate the true beauty of this Heart Ring please view the video for a glimpse of this Heart Ring in all of its glory.
You Receive:
x1 Heart Shaped Diamond Ring as pictured
x1 Satin Ring bag
x1 Packaging box as pictured (with a free option to personalise name/small message in Gold chrome)
Heart Ring Specifications:
This Heart Ring comes in platinum plated & 925 silver.
AAA Zirconia
Inlay (not glue)
Women's Ring Size Chart:
Be sure to view our Women's Ring Size Chart to determine the Women's ring size that you require. Our chart is also a Unisex Ring Size Chart so the ring size chart is a guide for all persons. We list our Ring Size's in US Ring Sizes.
Minx London Jewellery Store:
The Minx London team, models, influencers and our loved ones wear our heart rings & Minx London jewellery ourselves and have had no issues with discolouration etc... We simply keep our heart shaped ring diamond / jewellery & iced out rings clean and avoid harsh chemicals. We would Not list any jewellery products that has not been fully tested and approved from our in house jewellery specialists as well as received good feedback and reviews from those whom we give jewellery to try out.


text:
More than 11,000 elephants have been killed by ivory poachers in Gabon since 2004 according to new research.
The country is home to over half of Africa's forest elephants who are highly valued because of the quality of their tusks.
Campaigners say the situation in what was believed to be a safe haven for these elephants is "out of control."
They blame the ongoing high demand for jewellery and other ivory products in Asia.
Gabon holds about 13% of the forests of Central Africa but it is home to around 40,000 forest elephants, a smaller species that are attractive to poachers because their ivory is tinged with pink and is very hard.
The new research has been carried out by the Gabonese national parks agency (ANPN) alongside WWF and the Wildlife Conservation Society (WCS).
Cross border poachers
Dr Fiona Maisels of the WCS explained that they had analysed the population of elephants in the Minkebe national park and compared it with their data gathered in the same area 9 years ago.
"Between 44-77% of the elephants have been killed," she said. "In other words 11,100 elephants have been lost since 2004."
Much of the attention on elephant poaching has been in the neighbouring Democratic Republic of Congo but with demand for ivory growing and prices rocketing in recent years, poachers have sought out the forest elephants in the vast expanses of Minkebe.
And despite the efforts of the Gabonese government to bolster anti-poaching patrols, according to Bas Huijbregts from WWF, the authorities are failing.
"In an area like Minkebe which is about 30,000 sq km, that's about the size of Belgium, without any roads. It is very difficult to track poachers here," he said.
The authorities believe that between 50 and 100 elephants per day were being killed in the park in 2011. Much of the poaching has been carried out by gangs from neighbouring Cameroon, with ivory carried across the northern border by porters.
The high prices being paid for ivory in Asian markets are having a knock-on effect on attempts to control the trade in Gabon says Bas Huijbregts.
"Such a high value commodity, it is corrupting governance on all levels – there are checkpoints all over the place, but no one ever detects that ivory," he said.
"When arrests are made, they are often obstructed by government people who have a stake in the trade as well."
In June last year Gabon's president Ali Bongo Ondimba ordered the burning of the country's stockpile of seized ivory. However the poaching continues and is leading many conservationists to question the long term survival of elephants in Africa.
Professor Lee White who heads Gabon's national park system said that despite their best efforts, the situation is running out of control.
"If we do not turn the situation around quickly, the future of the elephant in Africa is doomed," he said. "These new results illustrate starkly just how dramatic the situation has become."
Campaigners say that next month's meeting of the convention on the international trade in endangered species (CITES) will be an opportunity for global governments to strengthen measures against ivory poaching.
Source: http://www.bbc.co.uk/news/science-environment-21352722


text:
The Dallas Mavericks have signed former Minnesota Timberwolves lottery pick Rashad McCants to a non-guaranteed contract for the rest of the preseason according to the Dallas Morning News' Eddie Sefko. McCants, a 6-foot-4 scorer, didn't play professional basketball last season due to a wealth of problems as chronicled by Tom Ziller here.
ESPN's Marc Stein goes a bit further, reporting that "there is a far better chance McCants winds up playing for the Mavericks' D-League affiliate (Texas Legends) in nearby Frisco than with the parent club."
This, of course, would be a huge coup for the Legends because they'll now be able to bring him in through the new NBA Development League allocation rules instead of having to use their first round draft pick on him when the D-League draft takes place on November 1, a draft McCants was apparently planning to be involved with before the Mavericks called according to Stein.
McCants, according to sources, was planning to submit his name for the D-League draft this month. By signing with Dallas this week, McCants removes himself from the D-League draft pool and must play for the expansion Legends -- co-owned by Mavericks president of basketball operations Donnie Nelson -- if he wants to be a D-Leaguer this season and they want him.
I'm assuming right about now every D-League team is working hard to develop a better relationship with their NBA affiliates because, if not, they're going to keep falling further behind as the NBA teams take advantage of these loopholes.
Not-so-fun fact: McCants' basketball career has rapidly gone down hill since breaking up with Khloe Kardashian. I'm guessing the quality of his girlfriends has improved, however.


text:
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
We've had several big events in the family this year which is why I'm writing to you collectively. The biggest event was the arrival of our first grandchild, April Hodge Greenberg, daughter of Dr. Susan Hodge and Dr. David Greenberg (both are Research Fellows at Washington University of St. Louis). April is a lovely and delightful infant. Is there a special sweetness to having a grandchild because one is spared the daily chores? Unfortunately, we are also missing the daily seeing and hearing and cuddling since wee April lives more than 500 miles away. Well, we shall be properly doting grandparents and plan to "spoil" her as often as we have the opportunity.
The other reason for writing this long and collective Christmas letter is that Phil received two honors this year. So, in addition to telling you about children and grandchild, let me tell you about husband and how his honors have been enjoyed by me.
The first event took place in a spectacularly furnished set of rooms in the State Department Building in Washington, D.C. in November. At the desk on which John Hancock or somebody of his time signed one of our historic documents, Phil signed a book thus signifying his formal acceptance of election to the National Academy of Engineering. I was enormously impressed by this process and by the surroundings. I wandered around touching tables and books, stroking cloisonne jars, checking out the lounges, looking at paintings and other early American period art including intricately carved wardrobes and some statuary. Much of this is normally out-of-bounds to sightseers; I knew that I might never have such a lovely opportunity to see and touch again. The next evening we attended the Academy banquet in formal "bib and tucker", feeling rather grand. Phil's mother came into town to attend with us, an extra bonus to have her there, too.
During the day Phil attended business meetings, discussed problems , and generally worked. But the astonishing part of that day was the way the Academy wives were treated. About 60 of us were shepherded around in Washington to a few places of tourist interest but in a decidedly non-tourist manner. We were taken behind the scenes, into semi-private or working areas, and escorted by curators rather than guides. I was completely willing to be treated as a VIP but had to remind myself several times that I had done nothing specific to deserve it and needn't develop a swelled head nor expect it as my due henceforth. However undeserved it was, I enjoyed it all quite thoroughly.
Phil's "elevation" to Honorary (Life) Membership in the American Society of Mechanical Engineers took place later in November with a multi-media presentation of his life and works (so far!). It was beautifully done, for me rather sentimental. Lisa, our youngest, was able to take a few days of vacation to be in Atlanta with us which made it even better. For the presentation-show, they used slides of photographs of Phil as a baby, of him with April asleep on his chest, and of many events in between including a unique shot of Phil on top of Mt. Ritter (taken by David Bogy) and several of his own beautiful and artistic nature photographs.
I am happy to report that none of this has affected him in any noticeable way. He's the same relaxed, informal person he's always been, wears shorts and sandals to the office from May to October, might wear them to the Guthrie Theater if I would agree to accompany him in such garb! He seems to face each new class with the same anticipation and concern, and he continues his research with papers and books spread across and around our large dining room table (while a handsome desk collects dust in the study).
Our two younger children are doing essentially what they were doing last year. Philip T. is a design engineer in a company which builds industrial buildings in the steel mill area of Northern Indiana. He passed the professional engineers' tests last spring and can now add PE after the BSCE on his office door. This makes him the first "real" engineer in the family even though his father has been called an engineer for many years. Elizabeth (Lisa) is a programmer-analyst with Control Data Corp. in Sunnyvale, CA. She has been working on a project very closely related to the computer operating system my Center is about to acquire. CDC has sent her to Minneapolis-St. Paul (where their computers are built) 3 times since early November to help debug part of the system. Having one of our far-flung family in town has been a rare and true pleasure.
I continue as Assistant Director of the University of Minnesota's instructional and research computer center. My particular area of responsibility includes, among other things, many of the activities organized to make our computers easy (or easier, at least!) for the university staff and students to use. I have no doubts about the importance of computers to the modern world, but considerable doubt is creeping upon me about the importance of my job to me and vice Versa. I have had two careers: full-time housewife and mother; then part-time housewife and mother plus full-time involvement with computers (with a little extra school and grad school thrown in along the way). Perhaps the time has come for a third modification. Recently, I read an article in which the authors posed a question something like this: if you suddenly discovered that, instead of 15 more years of professional life, you had 40, how would you use that time? I found this a most provocative question and I leave it with you as we approach the fresh new year of 1978. May it be a happy and productive one for you.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Phil joins me in sending best and happiest wishes to you, everyone. –
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Groundhog Day 1978
Dear Friends-and-Relations,
The alarm clock was set for 4:30 a.m., but as is so often the case I was wide-awake at 4. So I rose from my soft bed in a cozy cabin in Sequoia Park, moving quietly so as not to disturb my lovely bride of a mere 34+ years, donned warm clothes for this chilly August morning, grabbed my already-loaded light pack, and sallied forth. A short drive to the empty parking lot at the base of 600′ Moro Rock, and I was on my way.
By day, Moro Rock is infested by ladies in high heels, men in business suits, and barefoot teenagers all puffing up the easy trail to the top. But in the starlight I was alone. And with each step I felt more alone until soon I was at the level top. Alone between the sleeping park below me and the canopy of uncountable stars above. Between was a ring of hill silhouettes�and a complete circle clearly defined against the luminous sky. East was marked by an almost painfully brilliant Venus and a very slightly lighter sky color. West, below the horizon the lights of a distant town sparkled through a valley.
I unshipped my faithful Rollei camera and guessed wildly on some hand-held time exposures. Got a beautiful one of Venus I'd be happy to show with very little urging. I snacked from my knapsack. I sat on the rock, and I slowly paced the top, looking all directions, but chiefly East as I waited for the new day which was scheduled to begin just for my benefit. Do you recall the scene from Black Orpheus where Orpheus tells the boy that the sun would not rise unless he played it up on his guitar? Well, this morning of August 22, 1977, Orpheus could take the day off. Even without a guitar I knew the sun would rise for me.
Meanwhile, I think back over the past eventful year. It began on GHD 1977, an unseasonably warm day (with no shadow for the Groundhog) so I jogged home for the first time in 1977�and got caught by a TV Camera! So, at 6 p.m. that evening, there I was, sweatshirt and all, on the evening news�for all of 10 seconds!
The East is definitely lighter. Around the horizon again with my camera, now set at 2.8 and 1/5th.
Some seven weeks later, on March 23, I appeared on TV for the second time in two months�which was also the second time in my 56+ years. This was part of a delayed documentary of our particular Minneapolis neighborhood which had been shot the previous fall and showed me alongside my 5-foot tall Brussell Sprouts.
Most of the stars have faded now and Venus is dimming fast. There is a red spot on Sawtooth Peak just south of east. The sun is coming.
It was really a year of public exposure. Friday, July 1 dawned cloudless and comfortably cool and Thea and I easily persuaded each other that the weekend would probably be sweltering thunderstorms (or maybe snow�I've forgotten the details) so we should play hooky and pack a picnic lunch for nearby Pike Island. While there, we encountered the only other hiker on the Island who turned out to be Ben Kern, the nature columnist for our Minneapolis Tribune. And sure enough, there in his column July 10, we were mentioned by name, together with our wise observations about the relative advantages of engineering, computing, and hiking.
Venus has gone. A solitary little cloud in the northeast has turned from red to pink to white. Several swallows are swooping about Moro Rock. Time for just one more thought.
And that thought concerns, of course, the most important event of the year. Namely, the birth on March 5, 1977 of April Hodge Greenberg, the most beautiful and wonderful baby ever born anywhere (I know�Thea already told you about it. But with such understatement!).
Time to stop thinking and cock the camera. The Eastern sky is about to burst. There it is! A sliver of deep red. Click. Decrease the exposure. The sliver grows. Click. Still less exposure. Now a jagged semicircle. Click. Smallest opening at 1/500th. One more click as the sun bounds free of the distant mountains. A new day has begun, started by me�TV star, newspaper celebrity, and, most important, Grampa.
May this year be as good for you as the last one was for me.
Original letter was hand-written on plain paper (actually on the back of The American Society of Mechanical Engineers/Journal of Applied Mechanics stationery)
Extra bonus: some of Philip's notes for this letter, written in early 1977. View notes.


text:
A person who is ill and out of sorts, gives a doctor the status of God on earth. Isn't this status one to proud of? A status to be cherished isn't it? The very presence of a doctor instills immense confidence in a patient, an enviable position of a man.
After understanding the high and mighty position of a doctor as it is expected to be, let us analyse whether doctors to-day stand up to this high esteem. I'm afraid; the answer to this query will be very disappointing.
To-day, doctors are found to be most indifferent to their patients, callous about the treatment they render which makes me feel that the God we imagined in days gone by has changed his colour and form from an angel to a devil. Doctors who are dealing with human lives should be at least humane if not loving and caring.
However, in these days we find that doctors are not even humane and thus, how can men, patients look up to them as incarnations of God as done earlier. What I feel is that, the general image of doctors is now very low in the eyes of general public.
The public has realised much to its dismay that doctors are now only busy minting money as much as their profession can bring for them, and they have lost real touch with human beings, and human life.
It is true that all individuals have become money spinning machines but the doctors who once represented God, should have stayed out of this race for money. Alas! This has not happened and this profession is as corrupt as any other.
With this background in mind, if I were a doctor I would first and foremost try to recover from the dumps, the image of the profession, the broken image of doctors would be repaired by constant effort.
It would be my prime objective to identify myself with the patients, put myself in their sick shoes and then act. I am sure if this could be done sincerely, I would be able to understand the pangs of pain the poor patient would be undergoing.
This would first of all make me behave humanly with him. Next, instead of keeping an eye on the amount of money he can pay for the treatment, I would rather concentrate on the treatment to be given, with a singular eye to cure him fully and just not bother how much he can pay me for the service.
I'd agree that the doctor is working to earn money, yes, his work is his bread and butter for this, and I'd take money and lots of it from the very rich and then treat the poor patients free. With this balancing act I think I would be able to earn enough money to maintain my life and family and also earn a sea of goodwill from the huge number of poor people.
I would earn besides money, love, respect, and reverence. Thus, contrary to what doctors earn these days, that is heaps and heaps of money only, I would earn money though not in heaps, but, love and respect in heaps – what more can anyone want from society?
With this attitude, I am sure I would be able to help other doctors also to come out of this rut and muck of just amassing wealth, at the cost of all other finer feelings for the public.
It is not that all my patients would get well no- that's not the matter they would only be definitely convinced that, I did my best, I did not mislead them just to fleece a few more coins from them. This would be my real estate and earning for a lifetime.
I would always be available for my patients and because of this; I know that my family would suffer. This snag in my life would however, will not deter me from my good clean path of treating patients to my optimum capacity.


text:
The McKinney-Vento Homeless Education Assistance Act defines a homeless individual as one who lacks a fixed, regular, and adequate nighttime residence. If a family lives in any of the following situations, then pre-school-aged and school-aged children and youth in that family have certain rights and protections under this act.
If a parent or guardian of a preschool-or school-aged child or children believes any of the above applies to his or her family, he or she should contact the district's liaison for homeless education: Lanie Kent (205) 871-4608.
4400 Fair Oaks Drive Mountain Brook, AL 35213
Phone | 205-871-3595 Fax |


text:
Top Child Custody Attorney Tampa, FL
The bond between a parent and child is unique. When that bond is healthy and allowed to thrive, it can be the single most precious relationship in the lives of both parent and child. Unfortunately, tensions and practical challenges that traditionally influence child custody and child support disputes can threaten the health and stability of such bonds. As a result, it is critically important for parents to approach child custody and child support matters with the greatest of care. Working with a top Tampa, Florida child custody attorney will help to ensure that your legal strategy is strong and that you have the greatest possible chance of achieving your child custody and/or support goals.
Preparing for an Initial Consultation
When preparing to meet with a top Tampa, FL child custody attorney for the first time, it helps to write down any questions you may have about your situation, your legal case and/or your attorney's approach to representation in advance. If you are not comfortable with your representation, any tensions in your attorney-client relationship could impact the success of your case. As a result, it is important to begin communicating about your questions and concerns from the start. The more clarification you can obtain, the more likely you will be able to set your mind at ease.
In addition to asking questions about your case, do not hesitate to ask questions about your top Tampa, FL child custody attorney's level of experience, approach to cases like yours, fees, communication style and expectations for your legal process. There is no single "correct" approach to the attorney-client relationship. Voicing your concerns and learning about your lawyer's style will help you to understand how best to move forward and what to expect from the progression of your case. Given how sensitive and uniquely important your situation is, your attorney-client relationship should be strong from the start.
Legal Assistance Is Available
If you are faced with a child custody and/or child support matter and are in need of legal assistance, please do not hesitate to connect with an experienced child custody attorney Tampa, FL residents trust. Once you explain the details surrounding your situation, the team at The McKinney Law Group will be able to advise you of your legal options and respond to any questions or concerns you may have about your case. In addition, your attorney will be able to explicitly respond to any questions or concerns you may have about representation.
It is not always easy to find an attorney who "fits" your needs, priorities and vision for your family legal situation. But once you determine that working with a top Tampa, FL child custody attorney is going to suit your needs, you can focus on working towards your goals while receiving valuable legal guidance and assistance. Although searching for the right attorney is not always an easy journey, finding one that can work with you to realize the strongest possible legal approach to your case is well worth the effort.


text:
Physicists avoid highly mathematical work despite being trained in advanced mathematics, new research suggests.
The study, published in the New Journal of Physics, shows that physicists pay less attention to theories that are crammed with mathematical details. This suggests there are real and widespread barriers to communicating mathematical work, and that this is not because of poor training in mathematical skills, or because there is a social stigma about doing well in mathematics.
Dr. Tim Fawcett and Dr. Andrew Higginson, from the University of Exeter, found, using statistical analysis of the number of citations to 2000 articles in a leading physics journal, that articles are less likely to be referenced by other physicists if they have lots of mathematical equations on each page. (1)
Mathematics is a far too accurate tool to depict the truth.
The truth is elusive.
The truth is subjective.
The truth is mystical.
Look beyond 1+1=2…
Look beyond the equations…
The meaning of what you want to say, cannot be said with numbers. The essence of what you want to express, cannot be expressed with words. First of all we need to understand. How we express what we understand comes afterwards and is a matter of choice.
Back in the days of Pythagoras, members of an elite cast discovered that not everything can be expressed as numbers. They decided to keep the secret safe. They even murdered in order to accomplish that. They succeeded. For too many years people believed in numbers. For so long, people believed in the ability to articulate the "truth" with words and mathematical expressions.
We live in the days of quantum mechanics and consciousness research dead ends though. We are now starting to believe that perhaps not everything can be said.
Pythagoras was right about silence.
It is not just a matter of keeping secrets. It never was.
Is IS the tool which reveals truths!
Only if you stand long enough and listen to it…
Hippasus' silence is deafening…


text:
Click icons to find Joseph Millson social media sites
Joseph as Derek Yates in the the first 2 episodes of 24: Live Another Day. Broadcast on FOX in the US and Sky 1 in UK in May 2014.
Eight Days
Tango One
The Rover
DVDs and other items related to Joseph's career are included in the Amazon UK link. Items not available in UK, or on Amazon UK, are listed seperately.
Follow Joseph on Twitter
Click for Joseph on Instagram
Click the image to order
Copyright © 2019 Joseph Millson | Supporting Joseph Millson since 2006 | Site by Darcylicious


text:
Optimising code
"Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered."
— Donald Knuth.
Optimising code to make it run faster is an iterative process:
- Find the biggest bottleneck (the slowest part of your code).
- Try to eliminate it (you may not succeed but that's ok).
- Repeat until your code is "fast enough."
This sounds easy, but it's not.
Even experienced programmers have a hard time identifying bottlenecks in their code. Instead of relying on your intuition, you should profile your code: use realistic inputs and measure the run-time of each individual operation. Only once you've identified the most important bottlenecks can you attempt to eliminate them. It's difficult to provide general advice on improving performance, but I try my best with six techniques that can be applied in many situations. I'll also suggest a general strategy for performance optimisation that helps ensure that your faster code will still be correct code.
It's easy to get caught up in trying to remove all bottlenecks. Don't! Your time is valuable and is better spent analysing your data, not eliminating possible inefficiencies in your code. Be pragmatic: don't spend hours of your time to save seconds of computer time. To enforce this advice, you should set a goal time for your code and optimise only up to that goal. This means you will not eliminate all bottlenecks. Some you will not get to because you've met your goal. Others you may need to pass over and accept either because there is no quick and easy solution or because the code is already well optimised and no significant improvement is possible. Accept these possibilities and move on to the next candidate.
Measuring performance describes how to find the bottlenecks in your code using line profiling.
Improving performance outlines seven general strategies for improving the performance of your code.
Code organisation teaches you how to organise your code to make optimisation as easy, and bug free, as possible.
Already solved reminds you to look for existing solutions.
Do as little as possible emphasises the importance of being lazy: often the easiest way to make a function faster is to let it to do less work.
Vectorise concisely defines vectorisation, and shows you how to make the most of built-in functions.
Avoid copies discusses the performance perils of copying data.
Byte code compilation shows you how to take advantage of R's byte code compiler.
Case study: t-test pulls all the pieces together into a case study showing how to speed up repeated t-tests by ~1000x.
Parallelise teaches you how to use parallelisation to spread computation across all the cores in your computer.
Other techniques finishes the chapter with pointers to more resources that will help you write fast code.
In this chapter we'll be using the
lineprof package to understand the performance of R code. Get it with:
Measuring performance
To understand performance, you use a profiler. There are a number of different types of profilers. R uses a fairly simple type called a sampling or statistical profiler. A sampling profiler stops the execution of code every few milliseconds and records which function is currently executing (along with which function called that function, and so on). For example, consider
f(), below:
f <- function() {
g <- function() {
h <- function() {
(I use
lineprof::pause() instead of
Sys.sleep() because
Sys.sleep() does not appear in profiling outputs because as far as R can tell, it doesn't use up any computing time.)
If we profiled the execution of
f(), stopping the execution of code every 0.1 s, we'd see a profile like below. Each line represents one "tick" of the profiler (0.1 s in this case), and function calls are nested with
>. It shows that the code spends 0.1 s running
f(), then 0.2 s running
g(), then 0.1 s running
f() > g()
f() > g() > h()
f() > h()
If we actually profile
f(), using the code below, we're unlikely to get such a clear result.
tmp <- tempfile()
Rprof(tmp, interval = 0.1)
That's because profiling is hard to do accurately without slowing your code down by many orders of magnitude. The compromise that
RProf() makes, sampling, only has minimal impact on the overall performance, but is fundamentally stochastic. There's some variability in both the accuracy of the timer and in the time taken by each operation, so each time you profile you'll get a slightly different answer. Fortunately, pinpoint accuracy is not needed to identify the slowest parts of your code.
Rather than focussing on individual calls, we'll visualise aggregates using the lineprof package. There are a number of other options, like
summaryRprof(), the proftools package, and the profr package, but these tools are beyond the scope of this book. I wrote the
lineprof package as a simpler way to visualise profiling data. As the name suggests, the fundamental unit of analysis in
lineprof() is a line of code. This makes lineprof less precise than the alternatives (because a line of code can contain multiple function calls), but it's easier to understand the context.
To use
lineprof, we first save the code in a file and
source() it. Here
profiling-example.R contains the definition of
g(), and
h(). Note that you must use
source() to load the code. This is because lineprof uses srcrefs to match up the code to the profile, and the needed srcrefs are only created when you load code from disk. We then use
lineprof() to run our function and capture the timing output. Printing this object shows some basic information. For now, we'll just focus on the time column which estimates how long each line took to run and the ref column which tells us which line of code was run. The estimates aren't perfect, but the ratios look about right.
l <- lineprof(f())
#> time alloc release dups ref src
#> 1 0.074 0.001 0 0 profiling.R#2 f/pause
#> 2 0.143 0.002 0 0 profiling.R#3 f/g
#> 3 0.071 0.000 0 0 profiling.R#4 f/h
lineprof provides some functions to navigate through this data structure, but they're a bit clumsy. Instead, we'll start an interactive explorer using the shiny package.
shine(l) will open a new web page (or if you're using RStudio, a new pane) that shows your source code annotated with information about how long each line took to run.
shine() starts a shiny app which "blocks" your R session. To exit, you'll need to stop the process using escape or ctrl + c.
t column visualises how much time is spent on each line. (You'll learn about the other columns in memory profiling.) While not precise, it allows you to spot bottlenecks, and you can get precise numbers by hovering over each bar. This shows that twice as much time is spent on
g() as on
h(), so it would make sense to drill down into
g() for more details. To do so, click
This technique should allow you to quickly identify the major bottlenecks in your code.
There are some other limitations to profiling:
Profiling does not extend to C code. You can see if your R code calls C/C++ code but not what functions are called inside of your C/C++ code. Unfortunately, tools for profiling compiled code are beyond the scope of this book (i.e., I have no idea how to do it).
Similarly, you can't see what's going on inside primitive functions or byte code compiled code.
If you're doing a lot of functional programming with anonymous functions, it can be hard to figure out exactly which function is being called. The easiest way to work around this is to name your functions.
Lazy evaluation means that arguments are often evaluated inside another function. For example, in the following code, profiling would make it seem like
i()was called by
j()because the argument isn't evaluated until it's needed by
i <- function() { pause(0.1) 10 } j <- function(x) { x + 10 } j(i())
If this is confusing, you can create temporary variables to force computation to happen earlier.
Improving performance
"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified."
— Donald Knuth.
Once you've used profiling to identify a bottleneck, you need to make it faster. The following sections introduce you to a number of techniques that I've found broadly useful:
- Look for existing solutions.
- Do less work.
- Vectorise.
- Parallelise.
- Avoid copies.
- Byte-code compile.
A final technique is to rewrite in a faster language, like C++. That's a big topic and is covered in Rcpp.
Before we get into specific techniques, I'll first describe a general strategy and organisational style that's useful when working on performance.
Code organisation
There are two traps that are easy to fall into when trying to make your code faster:
- Writing faster but incorrect code.
- Writing code that you think is faster, but is actually no better.
The strategy outlined below will help you avoid these pitfalls.
When tackling a bottleneck, you're likely to come up with multiple approaches. Write a function for each approach, encapsulating all relevant behaviour. This makes it easier to check that each approach returns the correct result and to time how long it takes to run. To demonstrate the strategy, I'll compare two approaches for computing the mean:
mean1 <- function(x) mean(x)
mean2 <- function(x) sum(x) / length(x)
I recommend that you keep a record of everything you try, even the failures. If a similar problem occurs in the future, it'll be useful to see everything you've tried. To do this I often use R Markdown, which makes it easy to intermingle code with detailed comments and notes.
Next, generate a representative test case. The case should be big enough to capture the essence of your problem but small enough that it takes only a few seconds to run. You don't want it to take too long because you'll need to run the test case many times to compare approaches. On the other hand, you don't want the case to be too small because then results might not scale up to the real problem.
Use this test case to quickly check that all variants return the same result. An easy way to do so is with
stopifnot() and
all.equal(). For real problems with fewer possible outputs, you may need more tests to make sure that an approach doesn't accidentally return the correct answer. That's unlikely for the mean.
x <- runif(100)
stopifnot(all.equal(mean1(x), mean2(x)))
Finally, use the
microbenchmark package to compare how long each variation takes to run. For bigger problems, reduce the
times parameter so that it only takes a couple of seconds to run. Focus on the median time, and use the upper and lower quartiles to gauge the variability of the measurement.
#> Unit: nanoseconds
#> expr min lq mean median uq max neval
#> mean1(x) 4,670 4,860 26557 5,020 5,220 2,150,000 100
#> mean2(x) 968 1,120 204006 1,340 1,420 20,300,000 100
(You might be surprised by the results:
mean(x) is considerably slower than
sum(x) / length(x). This is because, among other reasons,
mean(x) makes two passes over the vector to be more numerically accurate.)
Before you start experimenting, you should have a target speed that defines when the bottleneck is no longer a problem. Setting such a goal is important because you don't want to spend valuable time over-optimising your code.
If you'd like to see this strategy in action, I've used it a few times on stackoverflow:
- http://stackoverflow.com/questions/22515525#22518603
- http://stackoverflow.com/questions/22515175#22515856
- http://stackoverflow.com/questions/3476015#22511936
Has someone already solved the problem?
Once you've organised your code and captured all the variations you can think of, it's natural to see what others have done. You are part of a large community, and it's quite possible that someone has already tackled the same problem. If your bottleneck is a function in a package, it's worth looking at other packages that do the same thing. Two good places to start are:
CRAN task views. If there's a CRAN task view related to your problem domain, it's worth looking at the packages listed there.
Reverse dependencies of Rcpp, as listed on its CRAN page. Since these packages use C++, it's possible to find a solution to your bottleneck written in a higher performance language.
Otherwise, the challenge is describing your bottleneck in a way that helps you find related problems and solutions. Knowing the name of the problem or its synonyms will make this search much easier. But because you don't know what it's called, it's hard to search for it! By reading broadly about statistics and algorithms, you can build up your own knowledge base over time. Alternatively, ask others. Talk to your colleagues and brainstorm some possible names, then search on Google and stackoverflow. It's often helpful to restrict your search to R related pages. For Google, try rseek. For stackoverflow, restrict your search by including the R tag,
[R], in your search.
As discussed above, record all solutions that you find, not just those that immediately appear to be faster. Some solutions might be initially slower, but because they are easier to optimise they end up being faster. You may also be able to combine the fastest parts from different approaches. If you've found a solution that's fast enough, congratulations! If appropriate, you may want to share your solution with the R community. Otherwise, read on.
What are faster alternatives to
lm? Which are specifically designed to work with larger datasets?
What package implements a version of
match()that's faster for repeated lookups? How much faster is it?
List four functions (not just those in base R) that convert a string into a date time object. What are their strengths and weaknesses?
How many different ways can you compute a 1d density estimate in R?
Which packages provide the ability to compute a rolling mean?
What are the alternatives to
Do as little as possible
The easiest way to make a function faster is to let it do less work. One way to do that is use a function tailored to a more specific type of input or output, or a more specific problem. For example:
rowMeans(), and
colMeans()are faster than equivalent invocations that use
apply()because they are vectorised (the topic of the next section).
vapply()is faster than
sapply()because it pre-specifies the output type.
If you want to see if a vector contains a single value,
any(x == 10)is much faster than
10 %in% x. This is because testing equality is simpler than testing inclusion in a set.
Having this knowledge at your fingertips requires knowing that alternative functions exist: you need to have a good vocabulary. Start with the basics, and expand your vocab by regularly reading R code. Good places to read code are the R-help mailing list and stackoverflow.
Some functions coerce their inputs into a specific type. If your input is not the right type, the function has to do extra work. Instead, look for a function that works with your data as it is, or consider changing the way you store your data. The most common example of this problem is using
apply() on a data frame.
apply() always turns its input into a matrix. Not only is this error prone (because a data frame is more general than a matrix), it is also slower.
Other functions will do less work if you give them more information about the problem. It's always worthwhile to carefully read the documentation and experiment with different arguments. Some examples that I've discovered in the past include:
read.csv(): specify known column types with
factor(): specify known levels with
cut(): don't generate labels with
labels = FALSEif you don't need them, or, even better, use
findInterval()as mentioned in the "see also" section of the documentation.
unlist(x, use.names = FALSE)is much faster than
interaction(): if you only need combinations that exist in the data, use
drop = TRUE.
Sometimes you can make a function faster by avoiding method dispatch. As we saw in (Extreme dynamism), method dispatch in R can be costly. If you're calling a method in a tight loop, you can avoid some of the costs by doing the method lookup only once:
For S3, you can do this by calling
generic.class()instead of
For S4, you can do this by using
getMethod()to find the method, saving it to a variable, and then calling that function.
For example, calling
mean.default() quite a bit faster than calling
mean() for small vectors:
x <- runif(1e2)
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> mean(x) 3.69 3.98 5.15 4.22 5.09 32.2 100
#> mean.default(x) 1.51 1.79 2.42 2.05 2.30 36.7 100
This optimisation is a little risky. While
mean.default() is almost twice as fast, it'll fail in surprising ways if
x is not a numeric vector. You should only use it if you know for sure what
x is.
Knowing that you're dealing with a specific type of input can be another way to write faster code. For example,
as.data.frame() is quite slow because it coerces each element into a data frame and then
rbind()s them together. If you have a named list with vectors of equal length, you can directly transform it into a data frame. In this case, if you're able to make strong assumptions about your input, you can write a method that's about 20x faster than the default.
quickdf <- function(l) {
class(l) <- "data.frame"
attr(l, "row.names") <- .set_row_names(length(l[[1]]))
l <- lapply(1:26, function(i) runif(1e3))
names(l) <- letters
quick_df = quickdf(l),
as.data.frame = as.data.frame(l)
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> quick_df 13.9 20 98.2 30.2 39.9 6,690 100
#> as.data.frame 1,900.0 2,320 2804.3 2,680.0 2,960.0 7,590 100
Again, note the trade-off. This method is fast because it's dangerous. If you give it bad inputs, you'll get a corrupt data frame:
quickdf(list(x = 1, y = 1:2))
#> Warning in format.data.frame(if (omit) x[seq_len(n0), , drop = FALSE] else
#> x, : corrupt data frame: columns will be truncated or padded with NAs
#> x y
#> 1 1 1
To come up with this minimal method, I carefully read through and then rewrote the source code for
as.data.frame.list() and
data.frame(). I made many small changes, each time checking that I hadn't broken existing behaviour. After several hours work, I was able to isolate the minimal code shown above. This is a very useful technique. Most base R functions are written for flexibility and functionality, not performance. Thus, rewriting for your specific need can often yield substantial improvements. To do this, you'll need to read the source code. It can be complex and confusing, but don't give up!
The following example shows a progressive simplification of the
diff() function if you only want computing differences between adjacent values. At each step, I replace one argument with a specific case, and then check to see that the function still works. The initial function is long and complicated, but by restricting the arguments I not only make it around twice as fast, I also make it easier to understand.
First, I take the code of
diff() and reformat it to my style:
diff1 <- function (x, lag = 1L, differences = 1L) {
ismat <- is.matrix(x)
xlen <- if (ismat) dim(x)[1L] else length(x)
if (length(lag) > 1L || length(differences) > 1L ||
lag < 1L || differences < 1L)
stop("'lag' and 'differences' must be integers >= 1")
if (lag * differences >= xlen) {
r <- unclass(x)
i1 <- -seq_len(lag)
if (ismat) {
for (i in seq_len(differences)) {
r <- r[i1, , drop = FALSE] -
r[-nrow(r):-(nrow(r) - lag + 1L), , drop = FALSE]
} else {
for (i in seq_len(differences)) {
r <- r[i1] - r[-length(r):-(length(r) - lag + 1L)]
class(r) <- oldClass(x)
Next, I assume vector input. This allows me to remove the
is.matrix() test and the method that uses matrix subsetting.
diff2 <- function (x, lag = 1L, differences = 1L) {
xlen <- length(x)
if (length(lag) > 1L || length(differences) > 1L ||
lag < 1L || differences < 1L)
stop("'lag' and 'differences' must be integers >= 1")
if (lag * differences >= xlen) {
i1 <- -seq_len(lag)
for (i in seq_len(differences)) {
x <- x[i1] - x[-length(x):-(length(x) - lag + 1L)]
#> [1] 1 2 3 4 5 6 7 8 9 10
I now assume that
difference = 1L. This simplifies input checking and eliminates the for loop:
diff3 <- function (x, lag = 1L) {
xlen <- length(x)
if (length(lag) > 1L || lag < 1L)
stop("'lag' must be integer >= 1")
if (lag >= xlen) {
i1 <- -seq_len(lag)
x[i1] - x[-length(x):-(length(x) - lag + 1L)]
#> [1] 1 2 3 4 5 6 7 8 9 10
Finally I assume
lag = 1L. This eliminates input checking and simplifies subsetting.
diff4 <- function (x) {
xlen <- length(x)
if (xlen <= 1) return(x[0L])
x[-1] - x[-xlen]
#> [1] 1 2 3 4 5 6 7 8 9 10
diff4() is both considerably simpler and considerably faster than
x <- runif(100)
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> diff1(x) 5.81 6.53 390.96 7.95 8.54 38,300.0 100
#> diff2(x) 4.73 5.35 6.97 6.10 7.23 34.8 100
#> diff3(x) 4.05 4.85 197.79 5.76 6.33 19,100.0 100
#> diff4(x) 3.10 3.61 74.50 4.20 4.79 7,020.0 100
You'll be able to make
diff() even faster for this special case once you've read Rcpp.
A final example of doing less work is to use simpler data structures. For example, when working with rows from a data frame, it's often faster to work with row indices than data frames. For instance, if you wanted to compute a bootstrap estimate of the correlation between two columns in a data frame, there are two basic approaches: you can either work with the whole data frame or with the individual vectors. The following example shows that working with vectors is about twice as fast.
sample_rows <- function(df, i) sample.int(nrow(df), i,
replace = TRUE)
# Generate a new data frame containing randomly selected rows
boot_cor1 <- function(df, i) {
sub <- df[sample_rows(df, i), , drop = FALSE]
cor(sub$x, sub$y)
# Generate new vectors from random rows
boot_cor2 <- function(df, i ) {
idx <- sample_rows(df, i)
cor(df$x[idx], df$y[idx])
df <- data.frame(x = runif(100), y = runif(100))
boot_cor1(df, 10),
boot_cor2(df, 10)
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> boot_cor1(df, 10) 102 106.0 207 117.0 162.0 6,430 100
#> boot_cor2(df, 10) 46 48.1 135 49.8 61.1 4,930 100
How do the results change if you compare
mean.default()on 10,000 observations, rather than on 100?
The following code provides an alternative implementation of
rowSums(). Why is it faster for this input?
rowSums2 <- function(df) { out <- df[[1L]] if (ncol(df) == 1) return(out) for (i in 2:ncol(df)) { out <- out + df[[i]] } out } df <- as.data.frame( replicate(1e3, sample(100, 1e4, replace = TRUE)) ) system.time(rowSums(df)) #> user system elapsed #> 0.149 0.000 0.156 system.time(rowSums2(df)) #> user system elapsed #> 0.066 0.004 0.071
What's the difference between
Make a faster version of
chisq.test()that only computes the chi-square test statistic when the input is two numeric vectors with no missing values. You can try simplifying
chisq.test()or by coding from the mathematical definition.
Can you make a faster version of
table()for the case of an input of two integer vectors with no missing values? Can you use it to speed up your chi-square test?
Imagine you want to compute the bootstrap distribution of a sample correlation using
cor_df()and the data in the example below. Given that you want to run this many times, how can you make this code faster? (Hint: the function has three components that you can speed up.)
n <- 1e6 df <- data.frame(a = rnorm(n), b = rnorm(n)) cor_df <- function(df, n) { i <- sample(seq(n), n, replace = TRUE) cor(df[i, , drop = FALSE])[2,1] }
Is there a way to vectorise this procedure?
If you've used R for any length of time, you've probably heard the admonishment to "vectorise your code". But what does that actually mean? Vectorising your code is not just about avoiding for loops, although that's often a step. Vectorising is about taking a "whole object" approach to a problem, thinking about vectors, not scalars. There are two key attributes of a vectorised function:
It makes many problems simpler. Instead of having to think about the components of a vector, you only think about entire vectors.
The loops in a vectorised function are written in C instead of R. Loops in C are much faster because they have much less overhead.
Functionals stressed the importance of vectorised code as a higher level abstraction. Vectorisation is also important for writing fast R code. This doesn't mean simply using
apply() or
lapply(), or even
Vectorise(). Those functions improve the interface of a function, but don't fundamentally change performance. Using vectorisation for performance means finding the existing R function that is implemented in C and most closely applies to your problem.
Vectorised functions that apply to many common performance bottlenecks include:
rowMeans(), and
colMeans(). These vectorised matrix functions will always be faster than using
apply(). You can sometimes use these functions to build other vectorised functions.
rowAny <- function(x) rowSums(x) > 0 rowAll <- function(x) rowSums(x) == ncol(x)
Vectorised subsetting can lead to big improvements in speed. Remember the techniques behind lookup tables (lookup tables) and matching and merging by hand (matching and merging by hand). Also remember that you can use subsetting assignment to replace multiple values in a single step. If
xis a vector, matrix or data frame then
x[is.na(x)] <- 0will replace all missing values with 0.
If you're extracting or replacing values in scattered locations in a matrix or data frame, subset with an integer matrix. See matrix subsetting for more details.
If you're converting continuous values to categorical make sure you know how to use
Be aware of vectorised functions like
Matrix algebra is a general example of vectorisation. There loops are executed by highly tuned external libraries like BLAS. If you can figure out a way to use matrix algebra to solve your problem, you'll often get a very fast solution. The ability to solve problems with matrix algebra is a product of experience. While this skill is something you'll develop over time, a good place to start is to ask people with experience in your domain.
The downside of vectorisation is that it makes it harder to predict how operations will scale. The following example measures how long it takes to use character subsetting to lookup 1, 10, and 100 elements from a list. You might expect that looking up 10 elements would take 10x as long as looking up 1, and that looking up 100 elements would take 10x longer again. In fact, the following example shows that it only takes about 9 times longer to look up 100 elements than it does to look up 1.
lookup <- setNames(as.list(sample(100, 26)), letters)
x1 <- "j"
x10 <- sample(letters, 10)
x100 <- sample(letters, 100, replace = TRUE)
#> Unit: nanoseconds
#> expr min lq mean median uq max neval
#> lookup[x1] 751 904 1188 1,070 1,370 3,260 100
#> lookup[x10] 1,750 1,920 2430 2,090 2,410 25,500 100
#> lookup[x100] 6,420 7,530 9265 8,330 9,250 37,200 100
Vectorisation won't solve every problem, and rather than torturing an existing algorithm into one that uses a vectorised approach, you're often better off writing your own vectorised function in C++. You'll learn how to do so in Rcpp.
The density functions, e.g.,
dnorm(), have a common interface. Which arguments are vectorised over? What does
rnorm(10, mean = 10:1)do?
Compare the speed of
apply(x, 1, sum)with
rowSums(x)for varying sizes of
How can you use
crossprod()to compute a weighted sum? How much faster is it than the naive
sum(x * w)?
Avoid copies
A pernicious source of slow R code is growing an object with a loop. Whenever you use
rbind(), or
paste() to create a bigger object, R must first allocate space for the new object and then copy the old object to its new home. If you're repeating this many times, like in a for loop, this can be quite expensive. You've entered Circle 2 of the "R inferno".
Here's a little example that shows the problem. We first generate some random strings, and then combine them either iteratively with a loop using
collapse(), or in a single pass using
paste(). Note that the performance of
collapse() gets relatively worse as the number of strings grows: combining 100 strings takes almost 30 times longer than combining 10 strings.
random_string <- function() {
paste(sample(letters, 50, replace = TRUE), collapse = "")
strings10 <- replicate(10, random_string())
strings100 <- replicate(100, random_string())
collapse <- function(xs) {
out <- ""
for (x in xs) {
out <- paste0(out, x)
loop10 = collapse(strings10),
loop100 = collapse(strings100),
vec10 = paste(strings10, collapse = ""),
vec100 = paste(strings100, collapse = "")
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> loop10 26.10 28.50 38.8 35.0 45.2 111.0 100
#> loop100 876.00 921.00 1133.4 1,090.0 1,250.0 5,000.0 100
#> vec10 6.89 8.53 11.8 9.5 12.0 81.4 100
#> vec100 50.20 51.90 69.1 65.1 77.0 123.0 100
Modifying an object in a loop, e.g.,
x[i] <- y, can also create a copy, depending on the class of
x. Modification in place discusses this issue in more depth and gives you some tools to determine when you're making copies.
Byte code compilation
R 2.13.0 introduced a byte code compiler which can increase the speed of some code. Using the compiler is an easy way to get improvements in speed. Even if it doesn't work well for your function, you won't have invested a lot of time in the effort. The following example shows the pure R version of
lapply() from functionals. Compiling it gives a considerable speedup, although it's still not quite as fast as the C version provided by base R.
lapply2 <- function(x, f, ...) {
out <- vector("list", length(x))
for (i in seq_along(x)) {
out[[i]] <- f(x[[i]], ...)
lapply2_c <- compiler::cmpfun(lapply2)
x <- list(1:10, letters, c(F, T), NULL)
lapply2(x, is.null),
lapply2_c(x, is.null),
lapply(x, is.null)
#> Unit: microseconds
#> expr min lq mean median uq max neval
#> lapply2(x, is.null) 2.50 2.70 76.49 2.86 3.03 7,360.00 100
#> lapply2_c(x, is.null) 2.51 2.74 2.98 2.88 3.13 7.71 100
#> lapply(x, is.null) 3.13 3.36 3.66 3.51 3.70 13.20 100
Byte code compilation really helps here, but in most cases you're more likely to get a 5-10% improvement. All base R functions are byte code compiled by default.
Case study: t-test
The following case study shows how to make t-tests faster using some of the techniques described above. It's based on an example in "Computing thousands of test statistics simultaneously in R" by Holger Schwender and Tina Müller. I thoroughly recommend reading the paper in full to see the same idea applied to other tests.
Imagine we have run 1000 experiments (rows), each of which collects data on 50 individuals (columns). The first 25 individuals in each experiment are assigned to group 1 and the rest to group 2. We'll first generate some random data to represent this problem:
m <- 1000
n <- 50
X <- matrix(rnorm(m * n, mean = 10, sd = 3), nrow = m)
grp <- rep(1:2, each = n / 2)
For data in this form, there are two ways to use
t.test(). We can either use the formula interface or provide two vectors, one for each group. Timing reveals that the formula interface is considerably slower.
system.time(for(i in 1:m) t.test(X[i, ] ~ grp)$stat)
#> user system elapsed
#> 1.46 0.00 1.46
for(i in 1:m) t.test(X[i, grp == 1], X[i, grp == 2])$stat
#> user system elapsed
#> 0.254 0.000 0.255
Of course, a for loop computes, but doesn't save the values. We'll use
apply() to do that. This adds a little overhead:
compT <- function(x, grp){
t.test(x[grp == 1], x[grp == 2])$stat
system.time(t1 <- apply(X, 1, compT, grp = grp))
#> user system elapsed
#> 0.293 0.000 0.294
How can we make this faster? First, we could try doing less work. If you look at the source code of
stats:::t.test.default(), you'll see that it does a lot more than just compute the t-statistic. It also computes the p-value and formats the output for printing. We can try to make our code faster by stripping out those pieces.
my_t <- function(x, grp) {
t_stat <- function(x) {
m <- mean(x)
n <- length(x)
var <- sum((x - m) ^ 2) / (n - 1)
list(m = m, n = n, var = var)
g1 <- t_stat(x[grp == 1])
g2 <- t_stat(x[grp == 2])
se_total <- sqrt(g1$var / g1$n + g2$var / g2$n)
(g1$m - g2$m) / se_total
system.time(t2 <- apply(X, 1, my_t, grp = grp))
#> user system elapsed
#> 0.053 0.000 0.054
stopifnot(all.equal(t1, t2))
This gives us about a 6x speed improvement.
Now that we have a fairly simple function, we can make it faster still by vectorising it. Instead of looping over the array outside the function, we will modify
t_stat() to work with a matrix of values. Thus,
mean() becomes
length() becomes
ncol(), and
sum() becomes
rowSums(). The rest of the code stays the same.
rowtstat <- function(X, grp){
t_stat <- function(X) {
m <- rowMeans(X)
n <- ncol(X)
var <- rowSums((X - m) ^ 2) / (n - 1)
list(m = m, n = n, var = var)
g1 <- t_stat(X[, grp == 1])
g2 <- t_stat(X[, grp == 2])
se_total <- sqrt(g1$var / g1$n + g2$var / g2$n)
(g1$m - g2$m) / se_total
system.time(t3 <- rowtstat(X, grp))
#> user system elapsed
#> 0.025 0.000 0.025
stopifnot(all.equal(t1, t3))
That's much faster! It's at least 40x faster than our previous effort, and around 1000x faster than where we started.
Finally, we could try byte code compilation. Here we'll need to use
microbenchmark() instead of
system.time() in order to get enough accuracy to see a difference:
rowtstat_bc <- compiler::cmpfun(rowtstat)
rowtstat(X, grp),
rowtstat_bc(X, grp),
unit = "ms"
#> Unit: milliseconds
#> expr min lq mean median uq max neval
#> rowtstat(X, grp) 1.16 1.46 1.70 1.60 1.93 2.40 100
#> rowtstat_bc(X, grp) 1.15 1.47 1.72 1.67 1.92 5.15 100
In this example, byte code compilation doesn't help at all.
Parallelisation uses multiple cores to work simultaneously on different parts of a problem. It doesn't reduce the computing time, but it saves your time because you're using more of your computer's resources. Parallel computing is a complex topic, and there's no way to cover it in depth here. Some resources I recommend are:
Parallel R by Q. Ethan McCallum and Stephen Weston.
Parallel Computing for Data Science by Norm Matloff.
What I want to show is a simple application of parallel computing to what are called "embarrassingly parallel problems". An embarrassingly parallel problem is one that's made up of many simple problems that can be solved independently. A great example of this is
lapply() because it operates on each element independently of the others. It's very easy to parallelise
lapply() on Linux and the Mac because you simply substitute
mclapply() for
lapply(). The following code snippet runs a trivial (but slow) function on all cores of your computer.
cores <- detectCores()
#> [1] 4
pause <- function(i) {
function(x) Sys.sleep(i)
system.time(lapply(1:10, pause(0.25)))
#> user system elapsed
#> 0.001 0.000 2.505
system.time(mclapply(1:10, pause(0.25), mc.cores = cores))
#> user system elapsed
#> 0.002 0.052 0.771
Life is a bit harder in Windows. You need to first set up a local cluster and then use
cluster <- makePSOCKcluster(cores)
system.time(parLapply(cluster, 1:10, function(i) Sys.sleep(i)))
#> user system elapsed
#> 0.005 0.001 27.059
The main difference between
mclapply() and
makePSOCKcluster() is that the individual processes generated by
mclapply() inherit from the current process, while those generated by
makePSOCKcluster() start with a fresh session. This means that most real code will need some setup. Use
clusterEvalQ() to run arbitrary code on each cluster and load needed packages, and
clusterExport() to copy objects in the current session to the remote sessions.
x <- 10
psock <- parallel::makePSOCKcluster(1L)
clusterEvalQ(psock, x)
#> Error: one node produced an error: object 'x' not found
clusterExport(psock, "x")
clusterEvalQ(psock, x)
#> [[1]]
#> [1] 10
There is some communication overhead with parallel computing. If the subproblems are very small, then parallelisation might hurt rather than help. It's also possible to distribute computation over a network of computers (not just the cores on your local computer) but that's beyond the scope of this book, because it gets increasingly complicated to balance computation and communication costs. A good place to start for more information is the high performance computing CRAN task view.
Other techniques
Being able to write fast R code is part of being a good R programmer. Beyond the specific hints in this chapter, if you want to write fast R code, you'll need to improve your general programming skills. Some ways to do this are to:
Read R blogs to see what performance problems other people have struggled with, and how they have made their code faster.
Read other R programming books, like Norm Matloff's The Art of R Programming or Patrick Burns' R Inferno to learn about common traps.
Take an algorithms and data structure course to learn some well known ways of tackling certain classes of problems. I have heard good things about Princeton's Algorithms course offered on Coursera.
Read general books about optimisation like Mature optimisation by Carlos Bueno, or the Pragmatic Programmer by Andrew Hunt and David Thomas.
You can also reach out to the community for help. Stackoverflow can be a useful resource. You'll need to put some effort into creating an easily digestible example that also captures the salient features of your problem. If your example is too complex, few people will have the time and motivation to attempt a solution. If it's too simple, you'll get answers that solve the toy problem but not the real problem. If you also try to answer questions on stackoverflow, you'll quickly get a feel for what makes a good question.


text:
Located on the hillside above Neapolis, with an impressive view of Vatika Bay, this newly-built studio apartment offers serenity surrounded by olive trees, a ten-minute drive to the sea.
Park in an apron at the top of the driveway, then follow the stone footpath to the house. Along the way, a rock overhang offers a seating area and a summer kitchen. One flight of steps takes you from the footpath's terrace to the apartment's terrace. A second flight of steps leads to the owner's home. The terrace outside the apartment is solely for guests. WiFI Internet is included.
The studio apartment has a king-size bed and a sofa which pulls out into a wide single bed. The fully-equipped galley kitchen has a two-burner gas stove top, under-the-counter refrigerator, coffee maker and stove-top expresso maker. The fully-tiled shower has a large walk-in shower.
French doors and windows set in wide arches embrace a view of Elafonisos and Kythira Islands and the sea, which can be enjoyed from the bed and living room areas and the outside terrace.
The town of Neapolis is a ten-minute drive down the hill and offers tavernas, cafes, ouzerias, six bakeries, four grocery stores, and a variety of shops.
The beaches surrounding Vatika Bay are some of the most beautiful in Greece. Stretching from Neapolis to Pounta, small coves offer numerous secluded bathing spots. In town, beach umbrellas provide shade and the Limira Mare Hotel and Mone Mone Taverna offer umbrellas with drinks service. Beach bars at Narantzionas Beach and Manganos Beach offer beach volleyball. Simos Beach on Elafonisos Island commands an international reputation for its turquoise waters and shallow white sand. Elafonisos is a short ferry ride from Viglafia and, if you do not wish to take your car, a bus shuttle will take you from the ferry dock to Simos Beach.
Pavlopetri, the oldest underwater city in the world, is located near Pounta Beach. It is easy to snorkel over the ruins, which are located close to the beach in one to three meters of water. Foundations of large buildings, homes, courtyards, streets and cist graves are easy to distinguish. Two large chamber tombs are located just north of tiny Pavlopetri Island. About sixty smaller chamber tombs have been identified by archeologists on shore near Pavlopetri. A Roman canal that was created to allow sea water to flood a salt flat is still visible.
In May through July, visitors can volunteer to assist the local NGO Toulipa Goulymi in locating turtles' nests, then monitor the hatching eggs. The beaches from Pounta to Neapolis have been identified as an important nesting site for loggerhead turtles, Caretta caretta. When turtle tracks are found on early morning patrols, the NGO is notified and barriers and signs are put around the nest to protect the eggs. An approximate hatching date is noted on the sign so volunteers can monitor the nest and assist the hatchling turtles make their way to the sea.
One of the most spectacular caves in Europe is Kastania, about a twenty-minute drive from Neapolis. Guided tours are available regularly during the summer months. The modern cement walkways are easy to negotiate and creative lighting showcases colorful stalactites and stalagmites.
Hikers and mountain bikers can take advantage of a seemingly endless network of trails in the mountains and along the sea. Mountain bikes can be rented at the bike shop in Neapolis.
The newly-restored Byzantine fortress at Agia Paraskevi is a twenty-minute walk from the apartment. A stone pathway circles the fortress, then leads one inside. Informative signage explains the importance of the fortress, which dates from the 8th century. The superb views of Elafonisos Strait and Vatika Bay make it clear why this fortress served as an important strategic lookout.
The fascinating town of Monemvasia, the Gibraltar of Greece, is located a half-hour drive from the apartment. This well-known town has been lovingly restored and makes a great day-trip destination.
Other destinations include the rock-climbing area near the petrified palm forest, the Cape Malea lighthouse, the monastery of Agia Irini, and the island of Kythira.
Guests will be greeted personally by the owner of the property, who lives upstairs and is happy to help guests feel at home.


text:
Red Robin Gourmet Burgers issued the following statement on September 11 in response to a letter from Vintage Capital Management, LLC ("Vintage") dated September 10, 2019:
The Red Robin Board and management team are focused on executing the company's strategic plan to restore growth and improve profitability. The board appreciates input from all shareholders toward our shared goal of enhancing value and will continue to review the company's strategic priorities against all potential opportunities to create shareholder value.
Consistent with our stated priorities, last week we announced that Paul J.B. Murphy III will join Red Robin as president, chief executive officer and a member of the company's board of directors, effective October 3, 2019. Mr. Murphy is a proven restaurant industry executive with more than 30 years of operational, brand-positioning and turnaround expertise, as well as an extensive track record of creating significant shareholder value. We are excited about the company's potential to improve customer experience, significantly improve cash flow and increase profitability.
As previously announced, the Red Robin Board carefully reviewed and considered Vintage's proposal, consistent with its fiduciary duties and in consultation with its legal and financial advisors. The board unanimously determined that the proposal undervalues Red Robin and is not in the best interests of all shareholders, as the strategic plan currently being implemented by Red Robin positions the company to deliver greater value to its shareholders than Vintage's proposal.


text:
If you haven't read Unconditionally Yours-His Version yet, I would recommend you to read it first and then hop onto this one.
Chapter 2 : Her Version
Kathy knew he was staring at her. Of course she wasn't dumb. He had followed her near the jewelry store as well. Couldn't he be less obvious? Quick glance and she already had a judgement for him. Tall, fair and handsome. Extra bonus for not wearing those low hanging saggy jeans. Now that she was cautious of his presence it was hard to concentrate on shopping. She picked up a neck piece randomly and started bargaining. The shopkeeper wouldn't agree but she wanted to come out as a strong-willed person now that she had an audience. She stood there adamant till the shopkeeper gave in. Wow!!! That was the first time she could bargain her way. This guy definitely brought out the best in her. He is a keeper!!! She laughed at her own thought. Nevertheless she was extremely pleased and that reflected in her face.
3 years into the relationship, he could still manage to give her those butterfly feelings in her stomach. Being around Ryan meant the world to her. He was the most caring person she had ever met. It was genuine and she could feel it. He was her go to person for everything. She just knew they were meant to be together. He always brought out the best of her. To be fair, the worst as well and she couldn't help it. She was trying hard not to complicate things between them but seemed to fail anyways. Somewhere the chord wasn't tuning in perfectly as it used to be.
R : I got you something.
K : Really? What is it?
R: Close your eyes. No cheating!
K : Done. Now faaaast please.
R : Okay! Okay! Here, take.
K : Ahan, this dress is gorgeous baby. You didn't have to buy it though.
R : Of course I had to. It's valentines today and you would look like a dream in this.
K : Thanks babes for the gesture but it must have cost you a bunch. You could have just asked me if I needed something. I would have bought something useful.
R : I don't understand. You don't like the dress? You're happy. Right?
K : Of course I am. As long as I have you with me. I am always happy . What I meant was you don't have to buy me something every time to fix my mood. A rose would work too.
R : You're confusing. If I give you a present you're not happy and if I don't give you anything, you're upset. I just don't understand you anymore. I need to freshen up my mind. Going out for a walk.
There it was again. The temper. Should have just kept quite. But this happened every time. He thought buying her stuffs would make things perfectly all right. Doesn't he understand it's not the things that he buys for her that makes her happy. She just wants to spend some time together. Just the day before, he went out for a team dinner and he informed her at the last moment. He knew after a long days work he was the only thing she was looking forward to, didn't even ask why her mood was off. He must have thought she was throwing a tantrum again but off late she felt he was never there when she needed him. She was losing herself. She didn't want to. Expectations hurt. Isn't it?
Of course she loved presents but he would rather cover up an argument by buying present rather than dealing it upfront with her. All she wanted was them to talk. She believed if you're in love you should talk openly about your feelings. If something is bothering you let the other person know rather than shutting it down in your heart. This outspoken nature of her was getting in the way now and she couldn't help control it. Ryan would always end up taking out double meaning for something which she didn't even mean. Since when did things become so complicated? She wasn't doing something wrong. Or was she?
Maybe things would be different if she stopped reacting to small things. She really wanted this relationship to work. But to make it work they both had to be on the same page first.
Love stories are meant to be sweet but what we see is just the first layer of thousand emotions that couples intend us to see. It's time to see what lies beneath in perfecting a relationship. Up for an unconventional ride?
Read what happens next in Chapter 3 : Done And Dusted ( Click Me)
Will they ever come together to sort out their differences or will they let it go and bottle up their feelings till something big comes up. If you don't already know bottled feelings cannot stay put for long . Before it bursts and questions their love, time will tell whether they are Trapped In Love Or Wrapped In Love?
With the hope that Love wins this time too,
I Heart You All ❤
Feel free to share and re-blog my posts if you like them. To have instant updates of what's happening in my life you can connect with me on Instagram: @alwaysmissbindas ~ Head Full Of Dreams ♥ and Twitter: Missbindas ♥
© 2019 Unconditionally Yours|Series by Missbindas ♣Featured image from Pixabay