Структура данных Pandas от узкой к широкой с сводной таблицей без агрегации - PullRequest
0 голосов
/ 11 ноября 2018

У меня есть кадр данных pandas, который содержит набор данных iris. Я хочу задать для этого фрейма данных только значения sepal_length и species, а затем изменить его так, чтобы столбцы представляли собой уникальные значения для species, а значения - значения для этого вида.

# load data into a dataframe
df = pd.read_csv('https://raw.githubusercontent.com/mwaskom/seaborn-data/master/iris.csv')

head(df)
+----+---------------+--------------+---------------+--------------+---------+
|    | sepal_length  | sepal_width  | petal_length  | petal_width  | species |
+----+---------------+--------------+---------------+--------------+---------+
| 0  |          5.1  |         3.5  |          1.4  |         0.2  | setosa  |
| 1  |          4.9  |         3.0  |          1.4  |         0.2  | setosa  |
| 2  |          4.7  |         3.2  |          1.3  |         0.2  | setosa  |
| 3  |          4.6  |         3.1  |          1.5  |         0.2  | setosa  |
| 4  |          5.0  |         3.6  |          1.4  |         0.2  | setosa  |
+----+---------------+--------------+---------------+--------------+---------+

Я могу сделать это, я беру данные из Панд, так как использую словарь для изменения данных, но я не могу понять, как это сделать в Пандах.

data = df.to_dict('records')

e = {}
for line in data:
    e[line['species']] = []

for line in data:
    e[line['species']].append(line['sepal_length'])

new = pd.DataFrame(e)

Вот что я хочу закончить:

+----+---------+-------------+-----------+
|    | setosa  | versicolor  | virginica |
+----+---------+-------------+-----------+
| 0  |    5.1  |        7.0  |       6.3 |
| 1  |    4.9  |        6.4  |       5.8 |
| 2  |    4.7  |        6.9  |       7.1 |
| 3  |    4.6  |        5.5  |       6.3 |
| 4  |    5.0  |        6.5  |       6.5 |
+----+---------+-------------+-----------+

Я пытался использовать pd.crosstab(df['sepal_length'], df['species']), но это не дает мне то, что я хочу. Я также пытался использовать df.pivot_table('sepal_length', columns='species'), и это тоже не так.

Что мне здесь не хватает?

Ответы [ 2 ]

0 голосов
/ 12 ноября 2018

IIUC вы можете использовать grouby.cumcount на species столбец и установить индекс, затем использовать pivot вместо pivot_table, который нетребуется agg функция.

df1 = df.set_index(df.groupby('species').cumcount())

df1 = df1.pivot(columns='species', values='sepal_length').rename_axis(None,axis=1)

print (df1)

   setosa  versicolor  virginica
0     5.1         7.0        6.3
1     4.9         6.4        5.8
2     4.7         6.9        7.1
3     4.6         5.5        6.3
4     5.0         6.5        6.5
0 голосов
/ 12 ноября 2018

То, что вы пытаетесь сделать, займет несколько шагов. (Код ниже предполагает использование стандартного «набора данных Iris» ).

  1. Во-первых, давайте подставим DataFrame только те столбцы, которые нам нужны.

    df_subset = df[['sepal_length','species']]
    
  2. Далее, используйте pandas.pivot (целое число pandas.pivot_table), чтобы преобразовать ваш DataFrame из "длинного" в "плоский".

    df_pivot = df_subset.pivot(columns='species',values='sepal_length')
    
  3. Теперь мы близки к тому, что вы хотели, но поскольку ваши три species столбца идут по одному и тому же индексу, сводные DataFrame возвращают NaN s для двух из трех столбцов для любой данной строки , Мы можем обойти это, по столбцам конкатенируя DataFrame при его повторной индексации. (По сути, создание трех DataFrames - по одному для каждого вида - и объединение их по новому индексу). Мы можем сделать это одним из двух способов:

    • Компактное решение:

      names = ['setosa','versicolor','virginica']
      
      df_final = pd.concat(map(lambda name: df_pivot[name].dropna().reset_index().drop('index',axis=1), names), axis=1) 
      
    • Что эквивалентно:

      df_final = pd.concat([
          df_pivot['setosa'].dropna().reset_index().drop('index',axis=1),
          df_pivot['versicolor'].dropna().reset_index().drop('index',axis=1),
          df_pivot['virginica'].dropna().reset_index().drop('index',axis=1)],axis=1)
      
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...