У меня есть фрейм данных со столбцами для каждого дня месяца. Для каждого дня у меня в столбце разные значения. Бывший
Emp Number 01-Jul 02-Jul 03-Jul 04-Jul 05-Jul 06-Jul 07-Jul 08-Jul 09-Jul
0 C1 WFH WFH WFH WFH WFH WOH WOH WFH WFH
1 C2 WFH WFH WFH WFH WFH WOH WOH WFH WFH
2 C3 WFH WFH WFH WFH WOH WOH WOH WFH WFH
3 C4 WFH WFH WFH WFH WOH WOH WOH WFH WFH
4 C5 WFH WFH WOH WOH WFH WOH WOH WFH WFH
Я хочу вывести как
C1 WFH 7, WOH 2,
C2 WFH 7, WOH 2
C3 WFH 6, WOH 3
C4 WFH 6, WOH 3
C5 WFH 5, WOH 4
Как мне перебрать эти столбцы и получить это количество и в каком типе данных мне захватить выходные данные?
Я попытался использовать подсчет значений и попытался зафиксировать их в типе данных Series. Это не работает.
Покажите, пожалуйста, что вы пробовали. Это помогает нам понять то, что вы уже знаете.
Вы импортируете эти значения из файла CSV или чего-то еще?
Поскольку DataFrames ориентированы на столбцы, вам потребуется изменить форму данных, чтобы получить правильное количество значений для каждой строки.
Кроме того, ожидаемый результат больше похож на отчет, а не на конкретный DataFrame, поэтому мы разобьем этот вопрос на две части:
from io import StringIO
buffer = StringIO('''
Emp Number 01-Jul 02-Jul 03-Jul 04-Jul 05-Jul 06-Jul 07-Jul 08-Jul 09-Jul
0 C1 WFH WFH WFH WFH WFH WOH WOH WFH WFH
1 C2 WFH WFH WFH WFH WFH WOH WOH WFH WFH
2 C3 WFH WFH WFH WFH WOH WOH WOH WFH WFH
3 C4 WFH WFH WFH WFH WOH WOH WOH WFH WFH
4 C5 WFH WFH WOH WOH WFH WOH WOH WFH WFH
''')
import pandas as pd
df = pd.read_table(buffer, sep=r'\s+')
# ① Aggregate data
counts = (
df.set_index(['Emp', 'Number'])
.T
.apply(lambda s: s.value_counts())
.T
)
print(counts)
# WFH WOH
# Emp Number
# 0 C1 7 2
# 1 C2 7 2
# 2 C3 6 3
# 3 C4 6 3
# 4 C5 5 4
# ② Generate report
for row in counts.itertuples():
print(f'{row.Index[1]} WFH {row.WFH}, WOH {row.WOH}')
# C1 WFH 7, WOH 2
# C2 WFH 7, WOH 2
# C3 WFH 6, WOH 3
# C4 WFH 6, WOH 3
# C5 WFH 5, WOH 4
Это отлично и в точку. Большое спасибо Кэмерону Ридделлу. Очень ценю это.
Большой! Если это решение вам подходит, не могли бы вы проголосовать за него и выбрать его как правильный ответ? Таким образом, если у кого-то еще возникнет аналогичный вопрос, он сможет быстро найти рабочее решение. Приятного кодирования :)
Для этого вы можете использовать .melt()
и .groupby()
с .size()
. Он более прост и эффективно использует функциональные возможности pandas
для изменения формы и подсчета данных.
Код:
# Reshape the DataFrame
df_melted = df.melt(id_vars=["Emp", "Number"], var_name = "Date", value_name = "Status")
# Group by 'Emp', 'Number' and 'Status', then count
result = df_melted.groupby(['Emp', 'Number', 'Status']).size().unstack(fill_value=0)
Выход:
for emp_number, row in result.iterrows(): status_counts = ', '.join(f'{status} {count}' for status, count in row.items()) print(f'{emp_number} {status_counts}')
> C1 WFH 7, WOH 2
> C2 WFH 7, WOH 2
> C3 WFH 6, WOH 3
> C4 WFH 6, WOH 3
> C5 WFH 5, WOH 4
Еще один способ с помощью agg
. Я думаю, это должно быть быстрее, чем apply
out = df.set_index(["Emp", "Number"]).agg(pd.Series.value_counts, axis=1).reset_index()
print(out)
Emp Number WFH WOH
0 0 C1 7 2
1 1 C2 7 2
2 2 C3 6 3
3 3 C4 6 3
4 4 C5 5 4
Вау... все отличные ответы... спасибо. Моя конечная цель — не отчет, а использование полученных результатов для дальнейших расчетов. Но все эти разные методы, я думаю, все они мне подойдут. Спасибо ребята.
@Рама, дело не в том, что работает, а в том, что работает лучше.
Пожалуйста, уточните вашу конкретную проблему или предоставьте дополнительную информацию, чтобы выделить именно то, что вам нужно. Поскольку сейчас написано, трудно точно сказать, о чем вы спрашиваете.