从数据框中删除重复列的最简单方法是什么?
我正在通过以下方式阅读具有重复列的文本文件:
import pandas as pd
df=pd.read_table(fname)
Run Code Online (Sandbox Code Playgroud)
列名是:
Time, Time Relative, N2, Time, Time Relative, H2, etc...
Run Code Online (Sandbox Code Playgroud)
所有时间和时间相对列包含相同的数据.我想要:
Time, Time Relative, N2, H2
Run Code Online (Sandbox Code Playgroud)
我所有的删除,删除等尝试,例如:
df=df.T.drop_duplicates().T
Run Code Online (Sandbox Code Playgroud)
导致唯一值索引错误:
Reindexing only valid with uniquely valued index objects
Run Code Online (Sandbox Code Playgroud)
很抱歉是熊猫菜鸟.任何建议,将不胜感激.
额外细节
Pandas版本:0.9.0
Python版本:2.7.3
Windows 7
(通过Pythonxy 2.7.3.0安装)
数据文件(注意:在真实文件中,列由制表符分隔,这里它们用4个空格分隔):
Time Time Relative [s] N2[%] Time Time Relative [s] H2[ppm]
2/12/2013 9:20:55 AM 6.177 9.99268e+001 2/12/2013 9:20:55 AM 6.177 3.216293e-005
2/12/2013 9:21:06 AM 17.689 9.99296e+001 2/12/2013 9:21:06 AM 17.689 3.841667e-005
2/12/2013 9:21:18 AM 29.186 9.992954e+001 2/12/2013 9:21:18 AM 29.186 3.880365e-005
... etc ...
2/12/2013 2:12:44 PM 17515.269 9.991756+001 2/12/2013 2:12:44 PM 17515.269 2.800279e-005
2/12/2013 2:12:55 PM 17526.769 9.991754e+001 2/12/2013 2:12:55 PM 17526.769 2.880386e-005
2/12/2013 2:13:07 PM 17538.273 9.991797e+001 2/12/2013 2:13:07 PM 17538.273 3.131447e-005
Run Code Online (Sandbox Code Playgroud)
Gen*_*sky 295
所有上述内容似乎都是不必要的沉重和乏味的方法 - 这是解决问题的一线解决方案.如果某些列名称重复并且您希望删除它们,则这适用:
df = df.loc[:,~df.columns.duplicated()]
Run Code Online (Sandbox Code Playgroud)
假设数据框的列是 ['alpha','beta','alpha']
df.columns.duplicated()返回一个布尔数组:a True或False每列.如果是,False那么列名在该点之前是唯一的,如果是,True则列名先前重复.例如,使用给定的示例,返回的值将是[False,False,True].
Pandas允许一个人使用布尔值进行索引,从而只选择True值.由于我们要保留不重复的列,我们需要翻转上面的布尔数组(即[True, True, False] = ~[False,False,True])
最后,df.loc[:,[True,True,False]]使用上述索引功能仅选择非重复列.
注意:上面只检查列名,而不是列值.
bea*_*rdc 37
听起来你已经知道了唯一的列名.如果是这样,那就行了df = df['Time', 'Time Relative', 'N2'].
如果没有,您的解决方案应该工作:
In [101]: vals = np.random.randint(0,20, (4,3))
vals
Out[101]:
array([[ 3, 13, 0],
[ 1, 15, 14],
[14, 19, 14],
[19, 5, 1]])
In [106]: df = pd.DataFrame(np.hstack([vals, vals]), columns=['Time', 'H1', 'N2', 'Time Relative', 'N2', 'Time'] )
df
Out[106]:
Time H1 N2 Time Relative N2 Time
0 3 13 0 3 13 0
1 1 15 14 1 15 14
2 14 19 14 14 19 14
3 19 5 1 19 5 1
In [107]: df.T.drop_duplicates().T
Out[107]:
Time H1 N2
0 3 13 0
1 1 15 14
2 14 19 14
3 19 5 1
Run Code Online (Sandbox Code Playgroud)
您可能有一些特定于您的数据的东西搞乱了.如果您可以向我们提供有关数据的更多详细信息,我们可以提供更多帮助.
编辑: 像安迪说的那样,问题可能在于重复的列标题.
对于示例表文件'dummy.csv',我编写了:
Time H1 N2 Time N2 Time Relative
3 13 13 3 13 0
1 15 15 1 15 14
14 19 19 14 19 14
19 5 5 19 5 1
Run Code Online (Sandbox Code Playgroud)
使用read_table提供唯一列并正常工作:
In [151]: df2 = pd.read_table('dummy.csv')
df2
Out[151]:
Time H1 N2 Time.1 N2.1 Time Relative
0 3 13 13 3 13 0
1 1 15 15 1 15 14
2 14 19 19 14 19 14
3 19 5 5 19 5 1
In [152]: df2.T.drop_duplicates().T
Out[152]:
Time H1 Time Relative
0 3 13 0
1 1 15 14
2 14 19 14
3 19 5 1
Run Code Online (Sandbox Code Playgroud)
如果您的版本不允许您使用,您可以将解决方案组合在一起以使其独一无二:
In [169]: df2 = pd.read_table('dummy.csv', header=None)
df2
Out[169]:
0 1 2 3 4 5
0 Time H1 N2 Time N2 Time Relative
1 3 13 13 3 13 0
2 1 15 15 1 15 14
3 14 19 19 14 19 14
4 19 5 5 19 5 1
In [171]: from collections import defaultdict
col_counts = defaultdict(int)
col_ix = df2.first_valid_index()
In [172]: cols = []
for col in df2.ix[col_ix]:
cnt = col_counts[col]
col_counts[col] += 1
suf = '_' + str(cnt) if cnt else ''
cols.append(col + suf)
cols
Out[172]:
['Time', 'H1', 'N2', 'Time_1', 'N2_1', 'Time Relative']
In [174]: df2.columns = cols
df2 = df2.drop([col_ix])
In [177]: df2
Out[177]:
Time H1 N2 Time_1 N2_1 Time Relative
1 3 13 13 3 13 0
2 1 15 15 1 15 14
3 14 19 19 14 19 14
4 19 5 5 19 5 1
In [178]: df2.T.drop_duplicates().T
Out[178]:
Time H1 Time Relative
1 3 13 0
2 1 15 14
3 14 19 14
4 19 5 1
Run Code Online (Sandbox Code Playgroud)
kal*_*alu 10
对于大型DataFrame,转置效率低下.这是一个替代方案:
def duplicate_columns(frame):
groups = frame.columns.to_series().groupby(frame.dtypes).groups
dups = []
for t, v in groups.items():
dcols = frame[v].to_dict(orient="list")
vs = dcols.values()
ks = dcols.keys()
lvs = len(vs)
for i in range(lvs):
for j in range(i+1,lvs):
if vs[i] == vs[j]:
dups.append(ks[i])
break
return dups
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
dups = duplicate_columns(frame)
frame = frame.drop(dups, axis=1)
Run Code Online (Sandbox Code Playgroud)
编辑
一个内存高效的版本,像任何其他值一样处理nans:
from pandas.core.common import array_equivalent
def duplicate_columns(frame):
groups = frame.columns.to_series().groupby(frame.dtypes).groups
dups = []
for t, v in groups.items():
cs = frame[v].columns
vs = frame[v]
lcs = len(cs)
for i in range(lcs):
ia = vs.iloc[:,i].values
for j in range(i+1, lcs):
ja = vs.iloc[:,j].values
if array_equivalent(ia, ja):
dups.append(cs[i])
break
return dups
Run Code Online (Sandbox Code Playgroud)
Ell*_*ins 10
如果我没有弄错的话,下面的内容是在没有转置解决方案的内存问题的情况下进行的,并且使用比@kalu函数更少的行,保留任何类似命名的列中的第一列.
Cols = list(df.columns)
for i,item in enumerate(df.columns):
if item in df.columns[:i]: Cols[i] = "toDROP"
df.columns = Cols
df = df.drop("toDROP",1)
Run Code Online (Sandbox Code Playgroud)
看起来你走在正确的道路上。这是您正在寻找的单线:
df.reset_index().T.drop_duplicates().T
Run Code Online (Sandbox Code Playgroud)
但是由于没有产生引用的错误消息的示例数据框Reindexing only valid with uniquely valued index objects,因此很难确切说明什么可以解决问题。如果恢复原始索引对您很重要,请执行以下操作:
original_index = df.index.names
df.reset_index().T.drop_duplicates().reset_index(original_index).T
Run Code Online (Sandbox Code Playgroud)
请注意,吉恩·伯林斯基 (Gene Burinsky) 的答案(在编写所选答案时)保留了每个重复列的第一个。保留最后一个:
df=df.loc[:, ~df.columns[::-1].duplicated()[::-1]]
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
102636 次 |
| 最近记录: |