Count number of occurrences of text over row python pandas

Viewed 51

I hope this is not too trivial, but I am kind of stuck. I am trying to count how many times the word "dog" appears in each row of a data frame. I then want to add the number in a new column.

This is how the dataframe looks like at the moment:

df_start = pd.DataFrame({'col1': ['House Home Dog', 0, 'Dog Flower Cat'], 'col2': ['Flower', 0, 0], 'col3': ['House Dog', 0, 'Dog Cat']})

I want to count how many times the word "dog" occurs in each row over multiple columns (in the final dataset I have more than 100 columns). The final result should look sth like this:

df_final = pd.DataFrame({'col1': ['House Home Dog', 0, 'Dog Flower Cat'], 'col2': ['Flower', 0, 0], 'col3': ['House Dog', 0, 'Dog Cat'], 'col4':[2, 0, 2]})

So far I am able to count the number of non null cells for each row or count how many times the word occurs in each column. But not the desired outcome. Thank you in advance for your help.

6 Answers

IIUC, this is what OP is looking for

df_start['dog_count'] = df_start.apply(lambda x: sum([i.lower().count('dog') for i in x if isinstance(i, str)]), axis=1)


[Out]:
             col1    col2       col3  dog_count
0  House Home Dog  Flower  House Dog          2
1               0       0          0          0
2  Dog Flower Cat       0    Dog Cat          2

This custom made function will count the word Dog, regardless of:

  • The capitalization. Be it Dog, DoG, dog,... those will be counted.

  • The number of times a word Dog appears in a specific cell.

If the dataframe looks like the following

df_start = pd.DataFrame({'col1': ['Dog Home Dog', 0, 'dog Flower Cat'], 'col2': ['Flower', 0, 0], 'col3': ['House Dog', 0, 'Dog Cat']})

[Out]:
             col1    col2       col3
0    Dog Home Dog  Flower  House Dog
1               0       0          0
2  dog Flower Cat       0    Dog Cat

After applying running the lambda function, one will get the following

             col1    col2       col3  dog_count
0    Dog Home Dog  Flower  House Dog          3
1               0       0          0          0
2  dog Flower Cat       0    Dog Cat          2

Notes:

  • The number of ways one can solve OP's question is immense, as there are various nuances one can come across, so, in order to provide an ideal solution, one would have access to the full dataframe, so that one could explore the various use cases.

  • This approach, even though might be ideal for OP's use case, also has some limitations. If one comes across the string Dogma, that will also be counted.

You can do it cleanly in one line

df['col4'] = df.apply(lambda x: x.str.contains('Dog')).sum(axis=1)

Here's a panda-esque way of doing it:

df_start["col4"] = (
df_start.apply(lambda col: col.str.lower() # make it lowercase
                    .str.count("dog")) # count 'dog's
                    .sum(axis=1) # take sum per row
                    .astype(int) # turn float to int
              )

Note that this will also count "dog" if it's just a substring of a word, like in "dogmatic".

here is one way to do it. one liner but split to add comments

df['col4']=df.apply(
    lambda x: (' '.join(map(str, list(x)) )) # create a string by combining all columns for each row
    .lower() # turn it to lower case
    .count('dog')  # count the word 'dog'
    , axis=1
)
df
              col1  col2    col3       col4
0   Dog Home Dog    Flower  House Dog   3
1              0    0       0           0
2   Dog Flower Cat  0       Dog Cat     2

The other solutions will give in case of the modified input

{'col1': ['House Home Doggy', 0, 'Dog Flower Cat'], 'col2': ['Dogdog Flower', 0, 0], 'col3': ['House dog', 0, 'Dog Cat']}

not what you would expect:

0  House Home Doggy  Dogdog Flower  House dog          4
1                 0              0          0          0
2    Dog Flower Cat              0    Dog Cat          2

The solution below does not count as shown above, but is counting only occurrences of the stand-alone phrase 'dog': :

import pandas as pd
df_start = pd.DataFrame({'col1': ['House Home Doggy', 0, 'Dog Flower Cat'], 'col2': ['Dogdog Flower', 0, 0], 'col3': ['House dog', 0, 'Dog Cat']})

def count_dogs(df_row):
   dogcount = 0
   for item in df_row:
       lst_item = str(item).split()
       for item in lst_item: 
           dogcount += 1 if item.lower() =="dog" else 0
   return dogcount
df_start['col4'] = df_start.apply(count_dogs, axis=1)    
print(df_start)

gives:

               col1           col2       col3  col4
0  House Home Doggy  Dogdog Flower  House dog     1
1                 0              0          0     0
2    Dog Flower Cat              0    Dog Cat     2

and with:

def count_dogs(df_row, casesensitive=True):
   dogcount = 0
   for item in df_row:
       lst_item = str(item).split()
       for item in lst_item: 
           if casesensitive: 
               dogcount += 1 if item =="Dog" else 0
           else:
               dogcount += 1 if item.lower() =="dog" else 0
   return dogcount
df_start['col4'] = df_start.apply(count_dogs, axis=1)    
print(df_start)

you will get:

0  House Home Doggy  Dogdog Flower  House dog     0
1                 0              0          0     0
2    Dog Flower Cat              0    Dog Cat     2

try:

df_start['col4'] = df_start.astype(str).sum(axis=1).str.lower().str.count("dog")

    col1            col2    col3        col4
0   House Home Dog  Flower  House Dog   2
1   0               0       0           0
2   Dog Flower Cat  0       Dog Cat     2
Related