我有一个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新手。对不起格式化不好。
答案 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
我得到了我想要的输出'固定代码'。