Python pandas: dataframe grouped by a column(such as, name), and get the value of some columns in each group
<p>There is dataframe called as df as following:</p>

<pre><code>  name   id    age             text 
   a      1     1    very good, and I like him
   b      2     2    I play basketball with his brother
   c      3     3    I hope to get a offer
   d      4     4    everything goes well, I think
   a      1     1    I will visit china
   b      2     2    no one can understand me, I will solve it
   c      3     3    I like followers
   d      4     4    maybe I will be good
   a      1     1    I should work hard to finish my research
   b      2     2    water is the source of earth, I agree it
   c      3     3    I hope you can keep in touch with me
   d      4     4    My baby is very cute, I like him
</code></pre>

<p>You know, there are four names: a, b, c, d. and each name has id, age, and text. Actually there id, age for each name group are the same, but the text is different for each name group, each name has three rows(this just example, the real data is a large data)</p>

<p>I want to get the id, age for each name group (for example). In addition, I want to caculate the character index in all text for each group in the text by the function: extract_text(text). I mean I want to get the following data: take the name 'a' as example: age: 1, id: 1. 'I' index in three rows(I just give a example, not the real): 20, 0, 0.</p>

<p>I have tried to do as following:</p>

<pre><code> import  pandas as pd

 def extract_text(text):
     index_n = None
     text_len = len(text)
     for i in range(0, text_len, 1):
         if text[i] == 'I':
            index_n = i
     return index_n



 df = pd.DataFrame({'name': ['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd',     
                            'a', 'b', 'c', 'd'],
               'id': [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4],
               'age':[1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4],
               'text':['very good, and I like him', 
                       'I play basketball with his brother',
                       'I hope to get a offer', 
                       'everything goes well, I think',
                       'I will visit china', 
                       'no one can understand me, I will solve it',
                       'I like followers', 'maybe I will be good',
                       'I should work hard to finish my research',                 
                       'water is the source of earth, I agree it',
                       'I hope you can keep in touch with me', 
                       'My baby is very cute, I like him']})


  id_num = df.groupby('name')['id'].value[0]
  id_num = df.groupby('age')['id'].value[0]
  index_num = df.groupby('age')['text'].apply(extract_text)
</code></pre>

<p>But there is error: </p>

<blockquote>
  <p>Traceback (most recent call last):File<br>
  bot_test_new.py", line 25, in <br>
  id_num = df.groupby('name')['id'].value[0]<br>
  AttributeError: 'SeriesGroupBy' object has no attribute 'value'</p>
</blockquote>

<p>Please give me you hand, thanks in advance!</p>

<p>I'll elaborate a bit more than in the comment. The problem is that extract_text is only able to handle individual strings. However when you groupby and then apply, you're sending a list with all the strings in the group.</p>

<p>There are two solutions, the first is the one I indicated (sending individual strings):</p>

<pre><code>index_num = df.groupby('age')['text'].apply(lambda x: [extract_text(_) for _ in x]) 
</code></pre>

<p>The other is changing extract_text so it can handle the list of strings:</p>

<pre><code> def extract_text(list_texts):
    list_index = []
    for text in list_texts:
        index_n = None
        text_len = len(text)
        for i in range(0, text_len, 1):
            if text[i] == 'I':
                index_n = i
        list_index.append(index_n)
    return list_index
</code></pre>

<p>And then continue with:</p>

<pre><code>index_num = df.groupby('age')['text'].apply(extract_text)
</code></pre>

<p>Moreover, you can use <code>text.find("I")</code> instead of your loop inside extract_text. Something like this <code>def extract_text(list_texts): return [text.find("I") for text in list_texts]</code>.</p>

python string pandas dataframe group-by