Подсчитайте значения после подчеркивания в серии Pandas

#python #pandas #dataframe

Вопрос:

У меня есть следующий фрейм данных:

ID event_1_positive событие_2_негативное event_3_neutral event_4_negative event_5_positive
1 1 1 0 1 0
2 1 0 0 0 1
3 0 1 1 1 0
4 1 1 0 0 0
5 0 0 1 1 1
6 0 1 1 0 1
7 1 1 1 0 0
8 0 1 0 0 0
9 1 1 1 1 0
10 0 0 0 0 1

Что я хотел бы сделать, так это упорядочить события по их эффекту (положительному, отрицательному или нейтральному) и вернуть количество для каждого эффекта.

В этом случае мой ожидаемый результат будет:

 0   negative   11
1   positive   9
2   neutral    5
 

Комментарии:

1. Знаете ли вы, когда появится отрицательный столбец, а когда появится положительный? или они могут быть случайными?

2. Они будут случайными.

Ответ №1:

Используйте filter и groupby :

 >>> df.filter(like='event') 
      .groupby(lambda x: x.rsplit('_', 1)[1], axis=1) 
      .sum().sum()

negative    11
neutral      5
positive     9
dtype: int64
 

Ответ №2:

Вы можете создать новые столбцы, в которые вы добавляете все столбцы с похожими эффектами, например df["negative"] = df["event_2_negative"] df["event_4_negative"] , а затем удалить другие столбцы, а затем выполнить df["negative"].value_counts() , например, или df["negative"].sum()

Ответ №3:

Это редкий случай, когда учет в цикле кажется практичным, поскольку существует управляемое количество столбцов

 # start a dictionary to pack with results
categories = {k: 0 for k in ("negative", "positive", "neutral")}

for colname in df:  # dataframes are iterable by-column name!
    if "_" not in colname:
        continue  # or consider alerting on this condition
    for category in categories.keys():
        if category in colname:  # substring compare
            categories[category]  = df[colname].sum()
            break  # successfully found category -> next colname
    else:  # didn't find and break
        raise ValueError(f"no category for {colname}")

# create a collection of results
df_results = pd.Series(categories).to_frame().reset_index()
 
     index      0
0   negative   11
1   positive   9
2   neutral    5
 

Ответ №4:

Одним из вариантов является изменение формы данных, когда у вас есть все отрицательные значения в одном столбце, одинаковые для положительных и нейтральных значений. У ваших столбцов есть шаблон (некоторые заканчиваются положительными значениями, некоторые столбцы заканчиваются нейтральными, …).

Мы можем использовать этот шаблон в pivot_longer из pyjanitor для изменения формы данных, а затем агрегирования (уменьшения):

 # pip install git https://github.com/pyjanitor-devs/pyjanitor.git
import pandas as pd
import janitor
(df.pivot_longer(index='ID', 
                 names_to=('positive', 'negative', 'neutral'), 
                 names_pattern=('positive', 'negative', 'neutral'))
   .iloc[:, 1:]
   .sum()
) 
positive     9.0
negative    11.0
neutral      5.0
dtype: float64
 

Ответ №5:

 df. 
drop("ID", axis=1). 
rename(columns=lambda x: x.split("_")[2]). 
unstack(). 
droplevel(1). 
reset_index(). 
groupby("index"). 
sum()

#           0
# index     
# negative  11
# neutral   5
# positive  9