使用该列中的值按特定列复制pandas中的行

时间:2017-09-04 13:02:49

标签: python pandas dataframe

解决此问题的最有效方法是什么?

i_have = pd.DataFrame(data={
  'id': ['A', 'B', 'C'],
  'v' : [ 's,m,l',  '1,2,3',   'k,g']
})

i_need = pd.DataFrame(data={
  'id': ['A','A','A','B','B','B','C', 'C'],
  'v' : ['s','m','l','1','2','3','k','g']
})

我想创建一个新的df,而迭代i_have会将记录追加到新的df中。但随着行数的增加,可能需要一段时间。

3 个答案:

答案 0 :(得分:3)

使用numpy.repeatnumpy.concatenate进行展平:

#create lists by split
splitted = i_have['v'].str.split(',')
#get legths of each lists 
lens = splitted.str.len()

df = pd.DataFrame({'id':np.repeat(i_have['id'], lens),
                    'v':np.concatenate(splitted)})
print (df)
  id  v
0  A  s
0  A  m
0  A  l
1  B  1
1  B  2
1  B  3
2  C  k
2  C  g

感谢piRSquared了解重复多列的解决方案:

i_have = pd.DataFrame(data={
  'id': ['A', 'B', 'C'],
  'id1': ['A1', 'B1', 'C1'],
  'v' : [ 's,m,l',  '1,2,3',   'k,g']
})
print (i_have)
  id id1      v
0  A  A1  s,m,l
1  B  B1  1,2,3
2  C  C1    k,g

splitted = i_have['v'].str.split(',')
lens = splitted.str.len()

df = i_have.loc[i_have.index.repeat(lens)].assign(v=np.concatenate(splitted))
print (df)
  id id1  v
0  A  A1  s
0  A  A1  m
0  A  A1  l
1  B  B1  1
1  B  B1  2
1  B  B1  3
2  C  C1  k
2  C  C1  g

答案 1 :(得分:1)

这是另一种方式

In [1667]: (i_have.set_index('id').v.str.split(',').apply(pd.Series)
                  .stack().reset_index(name='v').drop('level_1', 1))
Out[1667]:
  id  v
0  A  s
1  A  m
2  A  l
3  B  1
4  B  2
5  B  3
6  C  k
7  C  g

正如评论所指出的那样。

In [1672]: (i_have.set_index('id').v.str.split(',', expand=True)
                  .stack().reset_index(name='v').drop('level_1', 1))
Out[1672]:
  id  V
0  A  s
1  A  m
2  A  l
3  B  1
4  B  2
5  B  3
6  C  k
7  C  g

答案 2 :(得分:1)

如果您有多列,那么首先将数据按,expand = True分开(谢谢piRSquared),然后stackffill

i_have = pd.DataFrame(data={
  'id': ['A', 'B', 'C'],
  'v' : [ 's,m,l',  '1,2,3',   'k,g'],
  'w' : [ 's,8,l',  '1,2,3',   'k,g'],
  'x' : [ 's,0,l',  '1,21,3',   'ks,g'],
  'y' : [ 's,m,l',  '11,2,3',   'ks,g'],  
  'z' : [ 's,4,l',  '1,2,32',   'k,gs'],
})

i_want = i_have.apply(lambda x :x.str.split(',',expand=True).stack()).reset_index(level=1,drop=True).ffill()

如果值的大小不相等,那么

i_want = i_have.apply(lambda x :x.str.split(',',expand=True).stack()).reset_index(level=1,drop=True)
i_want['id'] = i_want['id'].ffill()

输出i_want

  id  v  w   x   y   z
0  A  s  s   s   s   s
1  A  m  8   0   m   4
2  A  l  l   l   l   l
3  B  1  1   1  11   1
4  B  2  2  21   2   2
5  B  3  3   3   3  32
6  C  k  k  ks  ks   k
7  C  g  g   g   g  gs