Python(Jupyter Notebook):Pandas复制数据帧索引导致值的长度不匹配索引错误的长度

时间:2017-09-28 19:59:46

标签: python pandas dataframe indexing split

我有一个pandas数据框,其中列中的单元格有多个值,并以';'分隔。我正在尝试拆分多个值(在一个单元格中)并为拆分的那些创建新行。类似下面的例子:

> In: df
> Out:
| Year | State | Ingredient | Species |
| 1998 |  CA   | egg; pork  | sp1;sp2 |

我想要实现的结果如下:

> In: df
> Out:
| Year | State | Ingredient | Species |
| 1998 |  CA   | egg        | sp1     |
| 1998 |  CA   | egg        | sp1     |
| 1998 |  CA   | pork       | sp2     |
| 1998 |  CA   | pork       | sp2     |

我找到了一个像这样分割数据帧的方法,但它只能工作一次。我使用的代码如下所示:

sp = df['Species'].str.split(';', expand=True).stack().reset_index(level=1, drop=True)
i = sp.index.get_level_values(0)
df1 = df.loc[i].copy()
df1['Species] = sp.values

当我首先在'Species'列上执行此操作时,使用原始数据框(df),它可以正常工作。

然而,当我在df1上再次执行此代码时,尝试拆分所有'Ingredient',它会给我一个错误,指出值的长度与索引的长度不匹配。如下图所示:

fd = df1['Ingredient'].str.split(';', expand=True).stack().reset_index(level=1, drop=True)
j = fd.index.get_level_values(0)
df2 = df1.loc[j].copy()
df2['Ingredient'] = fd.values

我做了很多试验,以找出为什么它会向我返回错误信息,并且我意识到当我在df1上再次执行此命令来创建df2时,它加倍行数/索引时我执行 df2 = df1.loc [j] .copy()。因此,给我更多的行,而不是我需要的。但是,如果我用'df'(原始数据帧)替换'df1',那么这个错误就不会出现并且有效。

有解决方法吗?或者还有其他分裂方法吗?

谢谢。

PS。这是我第一次在Stack Overflow上发帖,而且我也是Python新手。对不起格式化不好。

2 个答案:

答案 0 :(得分:2)

我试了一下你的问题。我无法解决你的方法中的问题。由于您提供了预期的输出,我能够提出另一种方法。希望这是简洁的,并解决您的问题。

df = pd.DataFrame(columns=['Year', 'State', 'Ingredient', 'Species'])
df.loc[0] = [1998, 'CA', 'egg; pork', 'sp1;sp2']   # Same input df as problem
print df
sp = df['Species'][0].split(';') # Separating by species
df = pd.concat([df]*len(sp), ignore_index=True) # Add len(sp) more rows
df['Species'] = sp
ing = df['Ingredient'][0].split(';')
df = pd.concat([df]*len(ing), ignore_index=True) 
df['Ingredient'] = ing*len(sp)    # Replicate ingredient len(sp) number of times
print df
   Year State Ingredient  Species
0  1998    CA  egg; pork  sp1;sp2
   Year State Ingredient Species
0  1998    CA        egg     sp1
1  1998    CA       pork     sp2
2  1998    CA        egg     sp1
3  1998    CA       pork     sp2

PS:这是我第一次回答...请告诉我是否应对此答案进行任何更改以添加更多详细信息或格式。谢谢!

编辑:我能找出你的方法出了什么问题。您必须在创建数据框的副本时重置索引,否则当您获得值为0的索引数时,您将获得多个值,因为它们当前都是0.请参阅下文。

sp = df['Species'].str.split(';', expand=True).stack().reset_index(level=1, drop=True)
i = sp.index.get_level_values(0)
df1 = df.loc[i].copy()
print df1
fd = df1['Ingredient'].str.split(';', expand=True).stack().reset_index(level=1, drop=True)
j = fd.index.get_level_values(0)
print j

df1 = df.loc[i].copy().reset_index(drop=True)
print df1
fd = df1['Ingredient'].str.split(';', expand=True).stack().reset_index(level=1, drop=True)
j = fd.index.get_level_values(0)
print j

输出:

   Year State Ingredient  Species
0  1998    CA  egg; pork  sp1;sp2
0  1998    CA  egg; pork  sp1;sp2
Int64Index([0, 0, 0, 0], dtype='int64')
   Year State Ingredient  Species
0  1998    CA  egg; pork  sp1;sp2
1  1998    CA  egg; pork  sp1;sp2
Int64Index([0, 0, 1, 1], dtype='int64')

带修复的原始代码:

df = pd.DataFrame(columns=['Year', 'State', 'Ingredient', 'Species'])
df.loc[0] = [1998, 'CA', 'egg; pork', 'sp1;sp2']
#print df

sp = df['Species'].str.split(';', expand=True).stack().reset_index(level=1, drop=True)
i = sp.index.get_level_values(0)
df1 = df.loc[i].copy().reset_index(drop=True, inplace=False)
df1['Species'] = sp.values


fd = df1['Ingredient'].str.split(';', expand=True).stack().reset_index(level=1, drop=True)
j = fd.index.get_level_values(0)
df2 = df1.loc[j].copy().reset_index(drop=True, inplace=False)
df2['Ingredient'] = fd.values
print df2

希望有所帮助!

答案 1 :(得分:1)

借助vk"原始代码修复"如上所示。它帮助我解决了错误"值的长度与索引的长度不匹配"。解决方案是:我需要将 reset_index()放在代码中的适当位置。

原始代码:

## Separate multiple entries in cells in 'Species' column to new rows:
sp = df['Species'].str.split(';', expand=True).stack().reset_index(level=1, drop=True)
i = sp.index.get_level_values(0)
df1 = df.loc[i].copy()
df1['Species] = sp.values

## Separate multiple entries in cells in 'Ingredient' column to new rows:
ing = df1['Ingredient'].str.split(';', expand=True).stack().reset_index(level=1, drop=True)
df2 = df1.loc[j].copy()
df2['Ingredient'] = ing.values

固定代码:

## Separate multiple entries in 'Species' column cell into rows
sp = df['Species'].str.split(';', expand=True).stack()
i = sp.index.get_level_values(0)
df1 = df.loc[i].copy().reset_index()
df1['Species'] = sp.values

del df1['index'] ## a column called "index" is generated when you execute reset_index()

## Separate multiple entries in 'Ingredient' column cell into rows:
ing = df1['Ingredient'].str.split(';', expand=True).stack()
j = ing.index.get_level_values(0)
df2 = df1.loc[j].copy()
df2['Ingredient'] = ing.values

我得到了我想要的输出'固定代码'。