我的下表是稀疏填充的,但在列中也有重复。
+------------+---------+
| LX ID | ISIN |
+------------+---------+
| A | X |
| B | Y |
| | Z |
| B | |
| | X |
| A | |
| B | Y |
| A | X |
+------------+---------+
使用df[["LX ID", "ISIN"]].drop_duplicates()
会产生以下内容,它会删除相同的行,但仍然在列中有重复项(例如最后3列):
+------------+---------+
| LX ID | ISIN |
+------------+---------+
| A | X |
| B | Y |
| | Z |
| B | |
| | X |
| A | |
+------------+---------+
你会提出什么解决方案,它会丢弃已经有一行更完整的行(例如,丢弃最后一行,因为第一行更好地填写)?最终浓缩表的一个例子如下:
+------------+---------+
| LX ID | ISIN |
+------------+---------+
| A | X |
| B | Y |
| | Z |
+------------+---------+
谢谢,
基兰
答案 0 :(得分:0)
以下是使用外部联接的一种方法,有两种风格..输入已经稍微调整,以证明具有两个值的行在具有一个值的行之前是有利的。
首先,设置:
In [1]: import pandas as pd
...:
...: ids = pd.DataFrame(
...: index=['LX ID', 'ISIN'],
...: data=[['A', 'B', '', 'B', '', 'A', 'B', 'A'],
...: ['', 'Y', 'Z', '', 'X', 'X', 'Y', 'X']],
...: ).T
...: ids
Out[1]:
LX ID ISIN
0 A
1 B Y
2 Z
3 B
4 X
5 A X
6 B Y
7 A X
然后按照“完整性”排序'
In [2]: ids['full'] = (ids['LX ID'] != '') & (ids['ISIN'] != '')
...: ids.sort_values('full', ascending=False, inplace=True)
...: ids
Out[2]:
LX ID ISIN full
1 B Y True
5 A X True
6 B Y True
7 A X True
0 A False
2 Z False
3 B False
4 X False
然后拆分两个系列,丢弃空白并删除重复项(默认情况下保留第一次出现):
lx = ids['LX ID']
isin = ids['ISIN']
lx = lx[lx != ''].drop_duplicates()
isin = isin[isin != ''].drop_duplicates()
然后在两种方式之一中使用外连接,用空字符串替换NaN ..正确的行连接在一起,因为保留了分隔两个系列时第一个数据框的隐式索引。
明确加入:
In [3]: pd.DataFrame(lx).join(isin, how='outer').fillna('')
Out[3]:
LX ID ISIN
1 B Y
2 Z
5 A X
或通过构造函数:
In [4]: pd.DataFrame([lx, isin]).T.fillna('')
Out[4]:
LX ID ISIN
1 B Y
2 Z
5 A X
如果我们有NaN而不是空格(如果从xls / csv读取,那么默认情况下可能是你得到的东西)可以简化整个事情:
In [5]: import pandas as pd
...: _ = pd.np.nan
...: ids = pd.DataFrame(
...: index=['LX ID', 'ISIN'],
...: data=[['A', _, 'B', _, 'B', _, 'A', 'B', 'A'],
...: [_, _, 'Y', 'Z', _, 'X', 'X', 'Y', 'X']],
...: ).T
...: ids
Out[5]:
LX ID ISIN
0 A NaN
1 NaN NaN
2 B Y
3 NaN Z
4 B NaN
5 NaN X
6 A X
7 B Y
8 A X
应用于行的count函数计算非NaN值,然后我们将其用于排序:
In [6]: ids['order'] = ids.count(axis=1)
...: ids.sort_values('order', ascending=False, inplace=True)
Out[6]:
LX ID ISIN order
2 B Y 2
6 A X 2
7 B Y 2
8 A X 2
0 A NaN 1
3 NaN Z 1
4 B NaN 1
5 NaN X 1
1 NaN NaN 0
然后类似于之前,但使用dropna()而不是显式空字符串比较:
In [7]: lx = ids['LX ID'].dropna().drop_duplicates()
...: isin = ids['ISIN'].dropna().drop_duplicates()
...: pd.DataFrame(lx).join(isin, how='outer')
Out[7]:
LX ID ISIN
2 B Y
3 NaN Z
6 A X