带有数据透视表的熊猫数据框从窄到宽没有聚合

时间:2018-11-11 19:28:42

标签: python pandas

我有一个熊猫数据框,其中包含iris数据集。我想对该数据框进行子集处理,使其仅包含sepal_lengthspecies,然后对其进行整形,以使列是species的唯一值,而值是该种类的值。 / p>

# 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 :(得分:2)

IIUC,您可以在species列上使用grouby.cumcount并设置索引,然后使用pivot代替pivot_table,这不需要agg函数。< / p>

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

答案 1 :(得分:1)

您要尝试做的事情将采取一些步骤。 (以下代码假定使用标准"Iris dataset")。

  1. 首先,让我们仅根据需要的列对DataFrame进行子集化。

    df_subset = df[['sepal_length','species']]
    
  2. 接下来,使用pandas.pivotpandas.pivot_table的中间符号)将DataFrame从“ long”转换为“ flat”。

    df_pivot = df_subset.pivot(columns='species',values='sepal_length')
    
  3. 现在,我们已经接近您想要的内容,但是由于您的三个species列沿相同的索引运行,所以透视的DataFrame会为其中两个返回NaN给定行的三列。我们可以通过在重新编制索引的同时按列连接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)