> ## Content Index
> Fetch the complete content index at: https://www.bambooweekly.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Bamboo Weekly #45: Netflix (solutions)
- URL: https://www.bambooweekly.com/bw-45-netflix-solution/
- Published: 2023-12-21T16:01:02.000Z
- Updated: 2026-08-23T09:36:59.000Z
- Description: Get better at: Excel, dates and times, missing data, grouping, formatting, using "apply", plotting, and regular expressions
- Author: Reuven M. Lerner
- Tags: excel, datetime, missing-data, grouping, formatting, apply-function, plotting, regular-expressions

This week, we looked at the data that Netflix revealed last week about what people are watching. This is after years in which Netflix had refused to reveal very much at all about what people were watching. Given their many millions of subscribers, and the billions that they were investing in new titles, it made sense that they wouldn’t want to let competitors know which of their shows were successful.

But a whole lot of things have changed — among them, the introduction of advertising into the streaming world — and Netflix is slowly starting to reveal at least a bit of what they know.

The data wasn’t as detailed as might have liked, and only described viewing habits during the first half (January - June) of 2023\. But it’s better than nothing, and already contains some interesting data for us to go through.

### Data and 8 questions

This week’s data was from the "engagement report" that they released on December 12th at [https://about.netflix.com/en/news/what-we-watched-a-netflix-engagement-report](https://about.netflix.com/en/news/what-we-watched-a-netflix-engagement-report?ref=bambooweekly.com). The data that they mentioned in the report is downloadable as an Excel file:

[/content/files/4cd45et68cgf/1HyknFM84ISQpeua6TjM7A/97a0a393098937a8f29c9d29c48dbfa8/what\_we\_watched\_a\_netflix\_engagement\_report\_2023jan-jun.xlsx](https://www.bambooweekly.com/content/files/4cd45et68cgf/1HyknFM84ISQpeua6TjM7A/97a0a393098937a8f29c9d29c48dbfa8/what%5Fwe%5Fwatched%5Fa%5Fnetflix%5Fengagement%5Freport%5F2023jan-jun.xlsx)

I asked eight questions this week about the data. Below are my solutions; a link the full Jupyter notebook I used to solve the problems is at the end of this post.

### Read the data from Excel into a data frame. Parse "Release Date" as a date.

Let’s start off by loading Pandas into memory:

```
import pandas as pd
```

With that in place, we can now use “[read\_excel](https://www.bambooweekly.com/pandas-read-excel/)” to load the spreadsheet into Pandas as a data frame. I downloaded the file, in part because I originally wasn’t sure how big it would be. (Turn out: It’s not that big.) I thus started off loading the file as follows:

```
filename = 'What_We_Watched_A_Netflix_Engagement_Report_2023Jan-Jun.xlsx'

df = pd.read_excel(filename)
```

That worked, in the sense that I got a data frame back. But it wasn’t accurate, largely because of the five rows of the Excel file used for the Netflix banner. The header lines were actually on row 6 of the spreadsheet — but because we use zero-based indexing in Python, we call that row 5 inside of Pandas.

While I was at it, I indicated that I only wanted column 1, 2, 3, and 4 (i.e., not the empty and useless first column, at index 0). The “usecols” keyword argument to read\_excel lets you use either names or index numbers for columns. Normally, I prefer to use names, because they’re easier to read and understand. But in this case, it just seemed easier to pass the integers.

Rather than pass a list of integers, I decided to just pass a call to “[range](https://docs.python.org/3/library/stdtypes.html?highlight=range&ref=bambooweekly.com#range)”, with a starting point of 1 and an ending point (i.e., one beyond the number I really want) of 5.

Finally, the “Release date” column should contain datetime information, and not be treated as strings. We could add the “parse\_dates” keyword argument to ensure that Pandas treats it correctly. But Excel has already tagged that column as containing datetime information, and that is passed along to read\_excel. So whereas we must use parse\_dates when we’re using “[read\_csv](https://www.bambooweekly.com/pandas-read-csv/)”, we don’t have to do it when we’re using Excel.

Our final query is thus:

```
filename = 'What_We_Watched_A_Netflix_Engagement_Report_2023Jan-Jun.xlsx'

df = pd.read_excel(filename, 
                   header=5, 
                  usecols=range(1, 5),
                  parse_dates=['Release Date'])
```

### Which columns, if any, have missing data? Is this significant?

One of the biggest issues with data analysis is the fact that data is often missing. We don’t want to represent that with any real value, such as 0, because it might get confused with actual values. In Pandas, we use either np.NaN (“not a number”), a float value from NumPy, or pd.NA, a more modern, flexible value that’s native to Pandas. Using these special not-a-value values allows us to find them, remove them, or replace them — but deciding just which of those would be appropriate very much depends on the circumstances.

In our case, I asked you to find out which columns have missing data. One trick that I’ve adopted is to invoke the “[isna](https://www.bambooweekly.com/pandas-isna/)” method on the data frame. That returns a new data frame with the same index and columns as our original, but with all True and False values.

We can then invoke “[sum](https://www.bambooweekly.com/pandas-sum/)” on the data frame. This sums up all of the values in each column, giving us a single integer value per column. But wait — if the output from “isna” is True or False, what happens when we sum each column?

Each True is treated as 1, and each False is treated as 0\. The result of this query is thus a series whose index represents the columns of our data frame, and whose integers reflect how many of the values in that column are NaN:

```
df.isna().sum()
```

What happens when I run this on our data frame?

```
Title                      0
Available Globally?        0
Release Date           13359
Hours Viewed               0
dtype: int64
```

In other words, we see that there are only NaN values in a single column, namely “Release Date”. And there are a *lot* of those values! I can run this query to find out just how many:

```
df.isna().sum() / len(df.index)
```

Notice that I run “len” on df.index, which I’ve learned is the fastest way to get the number of rows in a data frame. The result:

```
Title                  0.000000
Available Globally?    0.000000
Release Date           0.733447
Hours Viewed           0.000000
dtype: float64
```

There are only NaN values in the “Release Date” columns, but boy are there a lot of them, in 73 percent of the rows. Which means that for about three quarters of the titles in Netflix’s data set, we don’t know when it was released. I’d say that this is a significant piece of data that we could make sure of it were around. But

I should add that actually, we don’t have NaN or NA values in the “Release Date” column. You can see that if you sort the values, for example:

```
1209    2010-04-01
2758    2010-04-01
1844    2010-04-01
3391    2010-09-22
3205    2010-09-22
           ...    
18209          NaT
18210          NaT
18211          NaT
18212          NaT
18213          NaT
Name: Release Date, Length: 18214, dtype: datetime64[ns]
```

Notice those values at the bottom? Those are [NaT](https://pandas.pydata.org/docs/reference/api/pandas.NaT.html?ref=bambooweekly.com), short for “not a time,” and it’s the datetime equivalent to NaN. You can basically treat it as NaN, and it responds to the same methods as NaN, such as “[dropna](https://www.bambooweekly.com/pandas-dropna/)”. But it’s not *quite* the same thing.

### In this list of most-watched shows, how often does each year appear? And what is the mean number of hours viewed for each year's releases? Create a line plot.

We know that any query having to do with dates will ignore 75% of the data set, which is a shame. But even the 25% of data that does have date information can provide us with some interesting insights.

For example, I asked you to find how often each year appears in the catalog of titles that Netflix released. This means retrieving data from the “Release Date” column:

```
df['Release Date']
```

But what how can I count how often each year appear in this data set? First, I need to extract the year. That can be done with the [“dt” accessor, along with the “year” attribute](https://www.bambooweekly.com/pandas-dt-year/):

```
df['Release Date'].dt.year
```

The result is a series of integers, where each integer is the year in which the title was released. To find out how often each year appears, I can run “[value\_counts](https://www.bambooweekly.com/pandas-value-counts/)” on the results:

```
df['Release Date'].dt.year.value_counts()
```

I get a series back, one in which the distinct years (from the “Release Date” column) are the index, and the number of times each appears is the value:

```
Release Date
2022.0    956
2021.0    814
2020.0    779
2019.0    698
2018.0    595
2017.0    361
2023.0    329
2016.0    192
2015.0     79
2014.0     28
2013.0     12
2010.0      8
2011.0      3
2012.0      1
Name: count, dtype: int64
```

By default, value\_counts sorts its results from most common to least common. It would thus appear that Netflix has added more new titles each year, since more titles were added in 2022 than 2021, more in 2021 than 2020, more in 2020 than 2019, and so forth.

But wait — why is 2023 in the middle of the pack, with only 329 new releases?

It’s probably a combination of two factors: First, the data comes from the first half of the year, so there’s still plenty of time to catch up. Second, perhaps more titles are released in the second half of the year than the first. There might also be economic reasons; many companies have been feeling squeezed lately, and Netflix might have cut back on programming to some degree.

I then asked for us to see the mean number of hours watched for each release year. In other words, how many hours (on average) did people watch shows from 2023, 2022, 2021, etc.?

Whenever we want to get a result “for each value” of a particular column, we’re almost certainly going to use “[groupby](https://www.bambooweekly.com/pandas-groupby/)”. We say what column we want to group on, what column’s values we want to explore, and the aggregation method we want to use.

Here, we wanted to know:

- [Mean](https://www.bambooweekly.com/pandas-mean/) (our method)
- Hours watched (our value column)
- For each distinct year (our groupby column)

We can express that as follows:

```
df.groupby(df['Release Date'].dt.year)['Hours Viewed'].mean()
```

Notice that we can group on not just a column, but also on the result of invoking “dt.year” on the column.

Because we’re dealing with very large numbers, the output is a bit hard to read:

```
Release Date
2010.0    8.637500e+06
2011.0    3.566667e+07
2012.0    3.500000e+06
2013.0    1.162500e+07
2014.0    8.985714e+06
2015.0    7.789873e+06
2016.0    6.560417e+06
2017.0    6.383657e+06
2018.0    4.634118e+06
2019.0    5.296275e+06
2020.0    6.435944e+06
2021.0    8.048280e+06
2022.0    1.392584e+07
2023.0    5.213769e+07
Name: Hours Viewed, dtype: float64
```

I decided to round the numbers down to 2 decimal points, to make it a bit easier to understand:

```
df.groupby(df['Release Date'].dt.year)['Hours Viewed'].mean().round(2)
```

The result is certainly better:

```
Release Date
2010.0     8637500.00
2011.0    35666666.67
2012.0     3500000.00
2013.0    11625000.00
2014.0     8985714.29
2015.0     7789873.42
2016.0     6560416.67
2017.0     6383656.51
2018.0     4634117.65
2019.0     5296275.07
2020.0     6435943.52
2021.0     8048280.10
2022.0    13925836.82
2023.0    52137689.97
Name: Hours Viewed, dtype: float64
```

And yet, it’s still not as easy to understand as I might have hoped. I’ll add some commas between the numbers. And while I’m at it, I’ll break things up by line:

```
(
    df
    .groupby(df['Release Date'].dt.year)['Hours Viewed'].mean()
    .apply(lambda x: f'{x:,.2f}')
)
```

That final line invokes “[apply](https://www.bambooweekly.com/pandas-apply/)”, which lets us run a function on each value of the series. In this case, we use lambda for an anonymous function, one which puts the value inside of an f-string. As usual with an f-string, the format code comes after the “:” sign, and tells Python how to display the value. In this case:

- The “,” tells Python to put commas every 3 digits
- The “.” tells Python that we want to specify the number of digits after the decimal point, in this case 2 digits
- The “f” tells Python that we’re dealing with floating-point values

The final output is thus:

```
Release Date
2010.0     8,637,500.00
2011.0    35,666,666.67
2012.0     3,500,000.00
2013.0    11,625,000.00
2014.0     8,985,714.29
2015.0     7,789,873.42
2016.0     6,560,416.67
2017.0     6,383,656.51
2018.0     4,634,117.65
2019.0     5,296,275.07
2020.0     6,435,943.52
2021.0     8,048,280.10
2022.0    13,925,836.82
2023.0    52,137,689.97
Name: Hours Viewed, dtype: object
```

And yes, we see that on average, titles released in 2023 were viewed an average of 52 million hours. That’s far more than any other year, which tells me that people typically watch new shows. But wait — we also see lots of hours of watching from 2011\. What are people watching from then? Let’s take a look! I ran the following query:

```
(
    df.loc[df['Release Date'].dt.year == 2011]
    .set_index('Title')
    ['Hours Viewed']
    .apply(lambda x: f'{x:,.2f}')    
)
```

And I got:

```
Title
La Reina del Sur: Season 1     94,700,000.00
Trailer Park Boys: Season 7     7,500,000.00
Trailer Park Boys: Season 6     4,800,000.00
Name: Hours Viewed, dtype: object
```

I hadn’t ever heard of “La Reina del Sur,” but it’s apparently a [very popular Spanish-language telenovella](https://en.wikipedia.org/wiki/La%5FReina%5Fdel%5FSur%5F%28TV%5Fseries%29?ref=bambooweekly.com), and was watched quite a lot. The fact that it was watched a ton, and that there were only two other titles released in 2011, shows how an outlier than really skew the mean. That doesn’t happen with the median, which is why it’s often a more attractive measure.

But if we go back to my query for mean hours watched for each year’s releases:

```
(
    df
    .groupby(df['Release Date'].dt.year)['Hours Viewed'].mean()
    .apply(lambda x: f'{x:,.2f}')
)
```

How can I turn this into a plot? First, I’ll want to use “[sort\_index](https://www.bambooweekly.com/pandas-sort-index/)”, to ensure that the plot makes sense. Then I can use “[plot.line](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.plot.line.html?ref=bambooweekly.com)” to create a plot:

```
(
    df.groupby(df['Release Date'].dt.year)['Hours Viewed'].mean()
    .sort_index()
    .plot.line()
)
```

Here’s the plot I got:

![](https://storage.ghost.io/c/06/ba/06ba0cc0-be6f-4de7-af2f-5c20165279b9/content/images/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https-3a-2f-2fsubstack-post-media.s3.amazonaws.com-2fpublic-2fimages-2fd7e322ff-82fd-484a-9150-fdef2a0aaa4f_534x448.png)

We can see that people who watched in the first half of 2023 watched, on average, many more titles from 2023 than any other year. I’m guessing that it doesn’t hurt to have the new titles advertised on Netflix’s front page.

### When was the oldest show in this list released? What else was release on that date?

What is the oldest title in this list? Well, we can first use “[min](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.min.html?ref=bambooweekly.com)” to find the oldest release date:

```
df['Release Date'].min()
```

Notice how the min method works just fine with “datetime” columns; we don’t need to extract pieces with “dt”.

Next, we can find all of the titles released on that same date:

```
(
    df.loc[df['Release Date'] == df['Release Date'].min()]
    .set_index('Title')
    ['Hours Viewed']
    .apply(lambda x: f'{x:,.2f}')        
)
```

In other words:

- I found all of the titles released on the earliest date,
- I used “[set\_index](https://www.bambooweekly.com/pandas-set-index/)” to be the “Title” column
- I grabbed only the “Hours viewed” column, returning a series
- I formatted the series with the same lambda as before.

The result:

```
Title
Arrested Development: Season 1    17,600,000.00
Arrested Development: Season 2    11,300,000.00
Arrested Development: Season 3     7,000,000.00
Name: Hours Viewed, dtype: object
```

Which makes sense, because as we know, there’s always money in the banana stand.

![Generated by DALL·E](https://storage.ghost.io/c/06/ba/06ba0cc0-be6f-4de7-af2f-5c20165279b9/content/images/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https-3a-2f-2fsubstack-post-media.s3.amazonaws.com-2fpublic-2fimages-2f6ba08bfa-b134-404b-9727-57eacc436ea5_1024x1024.jpg)

If you don’t get this joke, then you *really* need to go and watch Arrested Development. Which, as we know, is available on Netflix.

### Are the same number of titles released each month? If not, in what months are the fewest new titles released? The most?

I don’t know much about the entertainment industry, but I wondered if they released more titles during some parts of the year than others. This prompted my question, namely how many titles are released each month of the year? And is there a big difference between them?

To calculate this, I used “[dt.month](https://www.bambooweekly.com/pandas-dt-month/)” to retrieve the month (regardless of year) from our titles:

```
(
    df
    ['Release Date'].dt.month
)
```

Then I used value\_counts to find out how often each of these appeared:

```
(
    df
    ['Release Date'].dt.month
    .value_counts()
)
```

I got the following results:

```
Release Date
10.0    469
12.0    465
11.0    429
3.0     419
9.0     416
6.0     413
4.0     401
8.0     385
5.0     382
1.0     363
7.0     363
2.0     350
Name: count, dtype: int64
```

In other words, October (month 10) has many more releases than February (month 2). And we can see that the last four months of the year appear in the top half of the output, confirming that it’s during those months that the most are released. (You can confirm this yourself by using “[dt.quarter](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.dt.quarter.html?ref=bambooweekly.com)” instead of “dt.month” in the above query.)

How can we automatically retrieve the months with the most and fewest releases? Well, the “[idxmin](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.idxmin.html?ref=bambooweekly.com)” and “[idxmax](https://www.bambooweekly.com/pandas-idxmax/)” methods return the index associated with the lowest and highest values, respectively. But if I want both of them, I can use the “[agg](https://www.bambooweekly.com/pandas-agg/)” method, then passing a list of strings, one for each method I want to run:

```
(
    df
    ['Release Date'].dt.month
    .value_counts()
    .agg(['idxmin', 'idxmax'])
)
```

This gives me the result:

```
idxmin     2.0
idxmax    10.0
Name: count, dtype: float64
```

We could, alternatively, also have grabbed the first and last items from the result of value\_counts, knowing that it sorts from highest to lowest:

```
(
    df
    ['Release Date'].dt.month
    .value_counts()
    .iloc[[0, -1]]
)
```

Here, I used “[iloc](https://www.bambooweekly.com/pandas-iloc/)”, which lets us retrieve based on the numeric position rather than the official index.

### Many shows are divided up by season. Count all hours viewed for a series, regardless of season. What are the the 20 top-ranked shows now, based on total number of viewing hours?

Netflix gave us data for each title, and counted each season as a separate title. What if we want to count all of the seasons for a show together?

The “Title” column of our data frame contains the titles of the various shows on Netflix. If a show has more than one season, then it is generally identified with a colon (“:”) followed by the word “Season”, a space, and one or more digits. This comes at the end of a title — although in the case of multilingual titles, there will then be a non-English name and numbering of the series.

I decided to use regular expressions here, and also to assume that removing everything from “: Season” and digits to the end of the line would do the job.

I started by creating a new, temporary column with “[assign](https://www.bambooweekly.com/pandas-assign/)”:

```
(
    df
    .assign(series_title = 
            df['Title'].replace(r':\s*Season\s*\d+.*', '', regex=True))
)
```

Here, I took the existing “Title” column and invoked “[replace](https://www.bambooweekly.com/pandas-replace/)” on it. The regular expression was:

- a literal colon, “:”
- zero or more whitespace characters, “\\s\*”
- the literal word “Season”
- zero or more whitespace characters, “\\s\*”
- one or more digits, “\\d+”
- zero or more additional characters, through the end of the string, “.\*”

I told Pandas to replace any text matching that pattern with the empty string.

I also passed the “regex=True” keyword argument, to ensure that my regular expression wouldn’t be interpreted literally.

With that assignment in place, I can then run groupby on the title, summing the hours viewed for all shows with the same title:

```
(
    df
    .assign(series_title = 
            df['Title'].replace(r':\s*Season\s*\d+.*', '', regex=True))
    .groupby('series_title')['Hours Viewed'].sum()
)
```

This gave me the total for all shows, but I was interested in the 20 shows with the highest sums. I thus invoked “[sort\_values](https://www.bambooweekly.com/pandas-sort-values/)”, and then “head” to get the top 20\. Finally, I applied our formatting lambda to put commas between numbers:

```
(
    df
    .assign(series_title = 
            df['Title'].replace(r':\s*Season\s*\d+.*', '', regex=True))
    .groupby('series_title')['Hours Viewed'].sum()
    .sort_values(ascending=False)
    .head(20)
    .apply(lambda x: f'{x:,}')        

)
```

The result:

```
series_title
Ginny & Georgia                        967,200,000
The Night Agent                        812,100,000
You                                    766,300,000
Outer Banks                            740,400,000
The Walking Dead                       738,600,000
The Glory                              622,800,000
La Reina del Sur                       616,800,000
CoComelon                              601,200,000
Suits (2011)                           599,100,000
The Blacklist                          596,900,000
Manifest                               581,900,000
Grey's Anatomy                         560,300,000
Wednesday                              507,700,000
Breaking Bad                           505,000,000
Queen Charlotte: A Bridgerton Story    503,000,000
Gilmore Girls                          488,700,000
Friends (1994)                         448,500,000
Lucifer                                434,300,000
The Big Bang Theory                    420,400,000
Shameless (U.S.)                       392,600,000
Name: Hours Viewed, dtype: object
```

What’s fascinating to me is that yes, there are some new, original Netflix productions here, including Ginny & Georgia (with a new season released in 2023) and The Night Agent (which was released in 2023). But then you have a ton of series like Suits, Grey’s Anatomy, Breaking Bad, Gilmore Girls, Friends, and the Big Bang Theory that are far from new, but which are clearly racking up lots of screen time.

### 7\. The \`guess\_language-spirit\` module on PyPI offers a function, \`guess\_language\`. If we use that on the show titles, and if we assume it's accurate, then what are the 10 top languages of Netflix titles? Should we really trust this data, based on the results we see?

Looking through the titles in the released data, it’s obvious that there are many non-English titles. I thought that it might be interesting to use a Python package that can identify languages to classify the titles. Maybe we’ll learn something about the non-English titles that Netflix is showing, and (more importantly) that people are watching.

That’s great, but… how can we identify the language used in the title? I looked around, and there are a number of different packages on PyPI that could help, but the “guess\_language-spirit” package seemed good enough, and didn’t require any additional software installations. I installed it with pip, and then imported it:

```
import guess_language
```

How, then, can I use this package to identify the language of a title? I’ll use “apply” again, this time with a named function:

```
(
    df['Title']
    .apply(guess_language.guessLanguage)
)
```

This returns a series of strings, most of them two-character language codes:

```
0         de
1         is
2         en
3    UNKNOWN
4         sv
5    UNKNOWN
6         ca
7    UNKNOWN
8         is
9    UNKNOWN
Name: Title, dtype: object
```

The above shows that the title at index 0 is in German, at index 1 is in is Icelandic, the third in English, the fourth unknown, and the fifth in Swedish. Let’s assume (for the time being) that these are accurate judgments. How often does each language appear?

We can find out by running value\_counts against the result of our function application:

```
(
    df['Title']
    .apply(guess_language.guessLanguage)
    .value_counts(normalize=True)
    .head(10)
)
```

The result is:

```
Title
UNKNOWN    0.430219
en         0.244702
fr         0.034040
it         0.023663
de         0.021247
es         0.020973
pt         0.015922
ca         0.015483
nb         0.012408
da         0.011584
Name: proportion, dtype: float64
```

The good news? This doesn’t seem totally crazy. If we ignore the unknown languages, we see English with 24 percent, then French, Italian, German, and Spanish. That doesn’t seem too far off from what could be reality.

The bad news actually comes in two parts:

First, the fact that 43 percent are labeled as “UNKNOWN” doesn’t give me a lot of faith in what we’re seeing.

Second, remember the first 10 languages we saw above? Let’s look at the titles:

```
0              The Night Agent: Season 1
1              Ginny & Georgia: Season 2
2     The Glory: Season 1 // 더 글로리: 시즌 1
3                    Wednesday: Season 1
4    Queen Charlotte: A Bridgerton Story
5                          You: Season 4
6             La Reina del Sur: Season 3
7                  Outer Banks: Season 3
8              Ginny & Georgia: Season 1
9                        FUBAR: Season 1
Name: Title, dtype: object
```

Just to remind you, the library I used identified The Night Agent as being in German, Ginny & Georgia as being in Icelandic, The Glory (with Korean characters!) as being in English, Queen Charlotte as being in Swedish, and La Reina del Sur as being in Catalan… all of which are totally wrong.

So this library is certainly fun to use, but I wouldn’t exactly depend on it for anything serious. I’m guessing that one of the other packages, perhaps one that has been trained on a more serious corpus of material, would do a better job.

### In how many different languages does Netflix release content each year? Has that number been rising? Create a line plot showing the number of different languages for each year. How can you explain the graph for 2023?

Finally, let’s pretend that the language-identification functionality is actually working. For each year, let’s count the number of different languages in which Netflix releases titles, and see if that number has been changing over time.

First, we’ll use “assign” to create a new, temporary column (“language”) from the result of applying our function:

```
(
    df
    .assign(language=df['Title'].apply(guess_language.guess_language))
)
```

With that in place, we can then run a groupby:

- Group by year
- Call the “[nunique](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.nunique.html?ref=bambooweekly.com)” method, which returns the number of distinct values in a series
- Invoke nunique on the new “language” column we just created

Here’s the code we can use for that:

```
(
    df
    .assign(language=df['Title'].apply(guess_language.guess_language))
    .groupby(df['Release Date'].dt.year)['language'].nunique()
)
```

Finally, we can use plot.line to graph it:

```
(
    df
    .assign(language=df['Title'].apply(guess_language.guess_language))
    .groupby(df['Release Date'].dt.year)['language'].nunique()
    .plot.line()
)
```

The result looks like this:

![](https://storage.ghost.io/c/06/ba/06ba0cc0-be6f-4de7-af2f-5c20165279b9/content/images/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https-3a-2f-2fsubstack-post-media.s3.amazonaws.com-2fpublic-2fimages-2fb1fbc5b9-d058-4915-a5e2-972bf16e580e_543x432.png)

I’ll grant you that the language-detection module doesn’t seem that accurate. But you know, the graph doesn’t seem totally wrong to me, given the huge investment that Netflix has reportedly been making in new, non-English content in the last number of years.

Why does the graph go down sharply from 2022 to 2023? I’m going to assume that if we were to have complete data for 2023, it would be the same as 2022, or even go up — but this data is just from the first part of the year, so it’s not a fair comparison.

That’s it for this week. My Jupyter notebook is here: [https://drive.google.com/file/d/1RCIZ8NkAnlwZ8xuIOXeqjYwRr30hLWCI/view?usp=sharing](https://drive.google.com/file/d/1RCIZ8NkAnlwZ8xuIOXeqjYwRr30hLWCI/view?usp=sharing&ref=bambooweekly.com).

I’ll be back next week with another set of Pandas problems based on current events.

Until then,

Reuven