首先,如果问题主题含糊不清,请道歉。我会尽力说清楚。 我有一个熊猫系列,如:
A
a1
b1
c1
B
a2
b2
c2
我们需要的是形成一个数据帧,其中{A,B}是第一列的值,每个值后面的值是第二列的值。对于我们的示例,例如:
A a1
A b1
A c1
B a2
B b2
B c2
我们在列表[A,B,...]中包含所有第一列标签。
我尝试了df.apply一些功能,这对我来说似乎完全不可能,更像是机器级代码。有人有想法吗?
答案 0 :(得分:2)
使用pd.Series.str.extract
d1 = s.str.extract('([A-Z])*(.+)*', expand=True)
d1[0].ffill(inplace=True)
d1.dropna()
0 1
1 A a1
2 A b1
3 A c1
5 B a2
6 B b2
7 B c2
答案 1 :(得分:2)
这是一种替代方法,它取决于标签列表中的成员资格,而不是字符串解析:
In [78]: labels = ["A", "B"]
In [79]: marks = s.isin(labels)
In [80]: pd.concat([s.where(marks).ffill(), s], axis=1).loc[~marks]
Out[80]:
0 1
1 A a1
2 A b1
3 A c1
5 B a2
6 B b2
7 B c2
一步一步,我们首先构建marks
,这是一个bool系列告诉我们每个新部分的开始位置:
In [22]: marks = s.isin(labels)
In [23]: marks
Out[23]:
0 True
1 False
2 False
3 False
4 True
5 False
6 False
7 False
dtype: bool
最初我计划将marks.cumsum()
用于groupby目的,但在这里使用where
更简单。
然后,我们可以使用s.where(marks).ffill()
来获取包含相应标签的系列:
In [24]: s.where(marks)
Out[24]:
0 A
1 NaN
2 NaN
3 NaN
4 B
5 NaN
6 NaN
7 NaN
dtype: object
In [25]: s.where(marks).ffill()
Out[25]:
0 A
1 A
2 A
3 A
4 B
5 B
6 B
7 B
dtype: object
之后,我们只是连接:
In [26]: pd.concat([s.where(marks).ffill(), s], axis=1)
Out[26]:
0 1
0 A A
1 A a1
2 A b1
3 A c1
4 B B
5 B a2
6 B b2
7 B c2
并使用.loc[~marks]
来保留不标记新部分开头的行:
In [27]: pd.concat([s.where(marks).ffill(), s], axis=1).loc[~marks]
Out[27]:
0 1
1 A a1
2 A b1
3 A c1
5 B a2
6 B b2
7 B c2
答案 2 :(得分:1)
使用Using no formatter input1[2017-10-20] date1 [2017-10-20]
Formatter MM/dd/yyyy input2[10/20/2017] date2 [2017-10-20]
isin
详细
In [3750]: cond = s.isin(L)
In [3751]: pd.concat([s.where(cond, np.nan).ffill(), s[~cond]], axis=1).dropna()
Out[3751]:
0 1
1 A a1
2 A b1
3 A c1
5 B a2
6 B b2
7 B c2
答案 3 :(得分:1)
上面发布了一些聪明而优雅的答案。仅仅为了比较,我还尝试了一种替代的基于缩减的方法,该方法在微基准测试中更快。它在我的机器上运行时间很短(比基于Pandas算子的几个解决方案快〜5倍)。
In [7]: # Setup test data
...: import itertools as it
...: labels = list('ABCDEFGH')
...: rawlist = [[l.lower() + str(i) for l in labels] for i in range(1,8)]
...: s = pd.Series(list(it.chain(*[[k] + vlist for k, vlist in zip(labels, rawlist)])))
In [8]: s.head(12)
Out[8]:
0 A
1 a1
2 b1
3 c1
4 d1
5 e1
6 f1
7 g1
8 h1
9 B
10 a2
11 b2
In [10]: # Setup reduction function
...: def _myreducer(acc, x):
...: """acc: [curr_label, [(label, related entry)]]"""
...: curr_label, label_entry_pair = acc
...: if x in labels:
...: acc[0] = x # curr_label is now x
...: else:
...: acc[1].append( (curr_label, x) ) # append (label, entry) pair
...: return acc
...:
...: reduced_tuple = reduce(_myreducer, s, [None, []])
In [11]: pd.DataFrame(reduced_tuple[1]).head(12)
...:
Out[11]:
0 1
0 A a1
1 A b1
2 A c1
3 A d1
4 A e1
5 A f1
6 A g1
7 A h1
8 B a2
9 B b2
10 B c2
11 B d2