.loc命令能否与groupby的apply函数一起使用?

huangapple go评论85阅读模式
英文:

Can the .loc command be used with groupby's apply function

问题

以下是您提供的代码部分的翻译:

  1. data = {'id': ['205', '205', '204', '204', '204'],
  2. 'Sentiment': ['Positive', 'Positive', 'Neutral', 'Positive', 'Positive']}
  3. df = pd.DataFrame(data)
  4. df['freq'] = df.groupby('Sentiment')['id'].transform(pd.Series.nunique)
  5. df['freq_sum'] = df.groupby('id')['freq'].transform(pd.Series.count)
  6. df['freq_cent'] = (df['freq'] / df['freq_sum'])
  7. df['sent_inclination'] = df.loc[df['freq_cent'] > 0.5, ['Sentiment']]

请注意,这是代码的翻译部分。如果您有任何其他问题或需要进一步的帮助,请随时提出。

英文:

This question already has answers here:
Pandas conditional creation of a series/dataframe column (13 answers)
Your post has been associated with a similar question. If that question doesn’t answer your issue, edit your question to highlight the difference between the associated question and yours. If edited, your question will be reviewed and might be reopened.

Find out more about duplicates and why your question has been closed.

Closed yesterday.

Hi. I have a DataFrame with multiple columns where I have successfully assigned values in a new column (sent_inclination) given a condition. However, I want to change the output such that the values are given to the entire given group identified by the column "id". The condition is: if "freq_cent" > 0.5, then the new column should have the value from the column 'Sentiment' in it for the given id. That is whether the freq_cent is greater than 0.5 or less than 0.5 for a given observation, the new column should contain the sentiment value that qualifies for greater than 0.5 for that entire group.
I am able to assign values to the entire DataFrame but cannot make sure that the values are the same for the entire group.

Here is my sample DataFrame:

  1. data = {'id': ['205', '205', '204', '204', '204'],
  2. 'Sentiment': ['Positive', 'Positive', 'Neutral', 'Positive', 'Positive']}
  3. df = pd.DataFrame(data)
  4. df['freq'] = df.groupby('Sentiment')['id'].transform(pd.Series.nunique)
  5. df['freq_sum'] = df.groupby('id')['freq'].transform(pd.Series.count)
  6. df['freq_cent'] = (df['freq']/df['freq_sum'])

where if I apply the code:

  1. df['sent_inclination'] = df.loc[df['freq_cent'] >0.5, ['Sentiment']]

I get the output:

  1. id Sentiment freq freq_sum freq_cent sent_inclination
  2. 0 205 Positive 2 2 1.000000 Positive
  3. 1 205 Positive 2 2 1.000000 Positive
  4. 2 204 Neutral 1 3 0.333333 NaN
  5. 3 204 Positive 2 3 0.666667 Positive
  6. 4 204 Positive 2 3 0.666667 Positive

The desired output should have 'sent_inclination' as Positive for all observations where id is 204, that is:

  1. id Sentiment freq freq_sum freq_cent sent_inclination
  2. 0 205 Positive 2 2 1.000000 Positive
  3. 1 205 Positive 2 2 1.000000 Positive
  4. 2 204 Neutral 1 3 0.333333 Positive
  5. 3 204 Positive 2 3 0.666667 Positive
  6. 4 204 Positive 2 3 0.666667 Positive

How can I achieve this? Any suggestions will be highly appreciated. Unfortunately the groupby.filter method doesn't work for me.

So far I have tried multiple codes, some of which are as follows:

  1. df['sent_inclination'] = df.loc[df.groupby('id').apply(lambda x: df.loc[df['freq_cent'] >0.5, df['Sentiment']])]
  2. df['sent_inclination'] = df.groupby('id').apply(lambda x: (df.query('freq_cent >0.5')['Sentiment']))
  3. df.groupby('id').apply(lambda x: x['sent_inclination'] == x['Sentiment'] if (x['freq_cent'] > 0.5) else '')
  4. df.groupby('id').apply(lambda x: x['sent_inclination'] == (df.query('freq_cent >0.5')['Sentiment']))

答案1

得分: 1

I recommend to use groupby from pandas and where from numpy:

  1. import pandas as pd
  2. import numpy as np
  3. # this will get you an appended dataframe where the maximum per group is picked (you can also use "mean" instead of "max" to get the group average)
  4. df = pd.merge(df, df.groupby(['id'])['freq_cent'].max().reset_index(), on='id', how='left')
  5. # this will check if the value is greater than 0.5
  6. df['sent_inclination'] = np.where(df['freq_cent_y'] > 0.5, 'Positive', df['Sentiment'])
  7. # cleaning and renaming
  8. df.rename(columns={"freq_cent_x": "freq_cent_x"}, inplace=True)
  9. df = df[['id', 'freq', 'freq_sum', 'freq_cent_x', 'sent_inclination']]

Output:

  1. print(df)
  2. id freq freq_sum freq_cent_x sent_inclination
  3. 0 205 2 2 1.000000 Positive
  4. 1 205 2 2 1.000000 Positive
  5. 2 204 1 3 0.333333 Positive
  6. 3 204 2 3 0.666667 Positive
  7. 4 204 2 3 0.666667 Positive

Based on the condition, you can also adjust it; simply change the line with np.where:

  1. df['sent_inclination'] = np.where(df['freq_cent_y'] > 0.5, 'Positive', np.where(df['freq_cent_y'] < 0.33, 'Negative', 'Neutral'))

This would give an outcome where >0.5 is "Positive," between 0.5 and 0.33 is "Neutral," and <0.33 is "Negative."

英文:

I recommend to use groupbyfrom pandas und wherefrom numpy:

  1. import pandas as pd
  2. import numpy as np
  3. #this will get you a appended dataframe where the maximum per group is picked (you can also use &quot;mean&quot; instead of &quot;max&quot; to get the group average
  4. df = pd.merge(df, df.groupby([&#39;id&#39;])[&#39;freq_cent&#39;].max().reset_index(), on=&#39;id&#39;, how=&#39;left&#39;)
  5. #this will check the value is greater then 0,5
  6. df[&#39;sent_inclination&#39;] = np.where(df[&#39;freq_cent_y&#39;] &gt;0.5, &#39;Positive&#39;, df[&#39;Sentiment&#39;])
  7. #cleaning and rename
  8. df.rename(columns={&quot;freq_cent_x&quot;: &quot;freq_cent_x&quot;}, inplace=True)
  9. df = df[[&#39;id&#39;, &#39;freq&#39;, &#39;freq_sum&#39;, &#39;freq_cent_x&#39;, &#39;sent_inclination&#39;]]

output:

  1. print(df)
  2. id freq freq_sum freq_cent_x sent_inclination
  3. 0 205 2 2 1.000000 Positive
  4. 1 205 2 2 1.000000 Positive
  5. 2 204 1 3 0.333333 Positive
  6. 3 204 2 3 0.666667 Positive
  7. 4 204 2 3 0.666667 Positive

Based on the condition you can also adjust it, simple change the line with np.where:

  1. df[&#39;sent_inclination&#39;] = np.where(df[&#39;freq_cent_y&#39;] &gt;0.5, &#39;Positive&#39;, np.where(df[&#39;freq_cent_y&#39; &lt;0.33, &#39;Negative&#39;, &#39;Neutral&#39;))

would give a outcome where >0.5 is "Positive", between 0.5 and 0.33 "Neutral", and <0.33 "Negative"

huangapple
  • 本文由 发表于 2023年5月11日 20:12:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76227539.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定