Pandas分组后统计Class_par_ratio频率及最大频率的实现问题
Let's fix this step by step, since you're working with Pandas 0.20 and Python 3.6.3, we'll make sure the code is fully compatible with your version.
问题回顾
Your goal is to take a DataFrame with columns FileName, PageNo, LineNo, Name, Class_par_ratio, and:
- Group by
FileNameandClass_par_ratioto calculate frequency (stored inFrequencycolumn) - Add a
Max Freq.column that shows the highest frequency value perFileNamegroup - Add a
Max_Classcolumn that shows whichClass_par_ratiocorresponds to that maximum frequency
Your previous attempts fell short:
- The first code snippet
df.groupby(['FileName'])['Class_par_ratio'].value_counts()only generated basic frequency stats, but didn't add the required max frequency columns or format the output correctly. - The second code had convoluted grouping logic—repeating the same groupby and using
agg({'count': max})was redundant (each group was already unique), andnlargest(1)only kept the top row perFileName, losing all other class data.
Correct Solution (Pandas 0.20 Compatible)
We'll break this into 3 clear steps:
1. Calculate Base Frequencies
First, count occurrences of each (FileName, Class_par_ratio) pair and name the frequency column:
# Count frequencies and reset index to get a flat DataFrame freq_df = df.groupby(['FileName', 'Class_par_ratio']).size().reset_index(name='Frequency')
For your sample data, this produces:
| FileName | Class_par_ratio | Frequency |
|---|---|---|
| 17973375 | MILK | 3 |
| 17973375 | OTHER FOODS | 1 |
| 17973375 | ANIMAL AND VEGETABLE OIL | 1 |
2. Add the Max Freq. Column
Use transform('max') to propagate the highest frequency value from each FileName group to every row in that group:
# Attach max frequency per FileName to all rows in the group freq_df['Max Freq.'] = freq_df.groupby('FileName')['Frequency'].transform('max')
3. Add the Max_Class Column
Find which Class_par_ratio has the maximum frequency per FileName, then merge this back to our main DataFrame:
# Get the Class_par_ratio with the highest frequency per FileName max_class_df = freq_df.loc[freq_df.groupby('FileName')['Frequency'].idxmax(), ['FileName', 'Class_par_ratio']] max_class_df.rename(columns={'Class_par_ratio': 'Max_Class'}, inplace=True) # Merge to add Max_Class to all rows in the original frequency DataFrame result_df = freq_df.merge(max_class_df, on='FileName', how='left')
Full Combined Code
# Step 1: Calculate frequencies freq_df = df.groupby(['FileName', 'Class_par_ratio']).size().reset_index(name='Frequency') # Step 2: Add max frequency column freq_df['Max Freq.'] = freq_df.groupby('FileName')['Frequency'].transform('max') # Step 3: Get and merge max frequency class max_class_df = freq_df.loc[freq_df.groupby('FileName')['Frequency'].idxmax(), ['FileName', 'Class_par_ratio']] max_class_df.rename(columns={'Class_par_ratio': 'Max_Class'}, inplace=True) result_df = freq_df.merge(max_class_df, on='FileName', how='left') # Optional: Reorder columns to match your expected output result_df = result_df[['FileName', 'Class_par_ratio', 'Frequency', 'Max_Class', 'Max Freq.']]
Sample Output (Matching Your Data)
Running this code on your sample data will produce:
| FileName | Class_par_ratio | Frequency | Max_Class | Max Freq. |
|---|---|---|---|---|
| 17973375 | MILK | 3 | MILK | 3 |
| 17973375 | OTHER FOODS | 1 | MILK | 3 |
| 17973375 | ANIMAL AND VEGETABLE OIL | 1 | MILK | 3 |
This fully meets your requirements: it retains all class entries, shows their individual frequencies, and includes the maximum frequency value and corresponding class for each FileName group.
内容的提问来源于stack exchange,提问作者Madhur Yadav

