Разделение фрейма данных не на основе строки, а на основе значения в столбце

#python #pandas #dataframe

#python #pandas #фрейм данных

Вопрос:

У меня есть фрейм данных, вырезанный из гораздо большего фрейма данных:

 import pandas as pd


data = {'Name': [5, 5, 6, 6, 7, 7],
        'Value': [1, 2, 1, 2, 1, 2]
            }

df = pd.DataFrame(data)

    Name    Value
0     5       1
1     5       2
2     6       1
3     6       2
4     7       1
5     7       2

Ideal Output:
    Name    Value  Value2
0     5       1      2
1     6       1      2
2     7       1      2
 

Мне нужен способ разделить фрейм данных на 2 отдельных фрейма данных на основе столбца «Значение». Строки с ‘1’ в столбце значений и строки с ‘2’ в столбце значений необходимо разделить.

Наилучшее / конечное решение — иметь одно имя, в котором 1 и 2 являются отдельными столбцами в одном фрейме данных. Моя идея до сих пор состоит в том, чтобы разделить два и объединить их, чтобы данные были рядом друг с другом и сводились к одному имени.

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

1. Можете ли вы добавить свой идеальный результат в свой вопрос, пожалуйста?

Ответ №1:

Вы можете сгруппировать по столбцу имени и объединить ваши значения в list .

 out = df.groupby('Name').agg(list).reset_index()
 
  1. Используйте DataFrame конструктор, чтобы разбить значение и присвоить их обратно:
 out[['Value1','Value2']] = pd.DataFrame(out.Value.tolist(), index= out.index)

>>> out.drop('Value',axis=1)

   Name  Value1  Value2
0     5       1       2
1     6       1       2
2     7       1       2
 
  1. Используйте pd.concat :
 >>> pd.concat([out['Name'],
              pd.DataFrame(out["Value"].to_list(), columns=['Value1', 'Value2'])],
              axis=1)

   Name  Value1  Value2
0     5       1       2
1     6       1       2
2     7       1       2
 

Завершите код, чтобы ответить на ваши комментарии:

Пример DF

 data = {'Name': [5, 5, 6, 6, 7, 7],
        'Value': [1, 2, 1, 2, 1, 2]
            }
df = pd.DataFrame(data)

   Name  Value
0     5      1
1     5      2
2     6      1
3     6      2
4     7      1
5     7      2
 

Ответ:

 out = df.groupby('Name').agg(list).reset_index()
out[['Value1','Value2']] = pd.DataFrame(out.Value.tolist(), index= out.index)
out.drop('Value',axis=1)

   Name  Value1  Value2
0     5       1       2
1     6       1       2
2     7       1       2
 

Дополнительные столбцы:

 data = {'Name': [5, 5, 6, 6, 7, 7],
        'Value': [1, 2, 1, 2, 1, 2],
        'extra':[1,2,3,4,5,6]
            }
df = pd.DataFrame(data)
out = df.groupby('Name').agg({'Value':list}).reset_index()
out[['Value1','Value2']] = pd.DataFrame(out.Value.tolist(), index= out.index)
out.drop('Value',axis=1,inplace=True)

result = pd.merge(df.drop('Value',axis=1),out,on='Name',how='left')

>>>result
 
   Name  extra  Value1  Value2
0     5      1       1       2
1     5      2       1       2
2     6      3       1       2
3     6      4       1       2
4     7      5       1       2
5     7      6       1       2
 

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

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

2. Вы выполнили первую команду, а затем один из двух вариантов?

3. Например, можете ли вы запустить весь последний блок в моем ответе?

4. Это то, что я сделал, и я получаю списки в виде значений вместо выделенных значений.

5. Ознакомьтесь с последней частью ответа. Я только что добавил ваши примерные данные, на которых я запускаю код, и результат. Можете ли вы попробовать еще раз? Если это не работает, я подозреваю, что это как-то связано с вашей версией pandas

Ответ №2:

Используйте pandas.DataFrame.groupby() :

 >>> df
   Name  Value
0     5      1
1     5      2
2     6      1
3     6      2
4     7      1
5     7      2

>>> dfs = [d for _, d in df.groupby('Value')]

>>> dfs
[   Name  Value
 0     5      1
 2     6      1
 4     7      1,
    Name  Value
 1     5      2
 3     6      2
 5     7      2]

>>> dfs[0]
   Name  Value
0     5      1
2     6      1
4     7      1

>>> dfs[1]
   Name  Value
1     5      2
3     6      2
5     7      2