python - Pandas:在列之间交换行
问题描述
有些行输入到错误的列中,所以现在我需要交换它们。
df = pd.DataFrame({'c': {0: '22:58:00', 1: '23:03:00', 2: '0', 3: '10'}, 'a': {0: '0', 1: '10', 2: '22:58:00', 3: '23:03:00'}, 'd': {0: '23:27:00', 1: '23:39:00', 2: '10', 3: '17'}, 'b': {0: '10', 1: '17', 2: '23:27:00', 3: '23:39:00'}})
a b c d
0 0 10 22:58:00 23:27:00
1 10 17 23:03:00 23:39:00
2 22:58:00 23:27:00 0 10
3 23:03:00 23:39:00 10 17
我目前的做法
cpy = df[['a', 'b']]
df.loc[2:, 'a'] = df['c']
df.loc[2:, 'b'] = df['d']
df.loc[2:, 'c'] = cpy['a']
df.loc[2:, 'd'] = cpy['b']
预期产出
a b c d
0 0 10 22:58:00 23:27:00
1 10 17 23:03:00 23:39:00
2 0 10 22:58:00 23:27:00
3 10 17 23:03:00 23:39:00
它有效,但这只是可能的,因为它是 4 列。有一个更好的方法吗?
请注意,dtypes 可能导致排序问题
df.loc[0]['c']
是datetime.time(22, 58)
也许有类似的东西
df.swap_row_col(index=[2:], columns_from=['a', 'b'], columns_to=['c', 'd'])
解决方案
方法一:np.sort
np.sort
pd.DataFrame
构造函数对我有用:
df = pd.DataFrame(np.sort(df.astype(str)), columns=df.columns)
a b c d
0 0 10 22:58:00 23:27:00
1 10 17 23:03:00 23:39:00
2 0 10 22:58:00 23:27:00
3 10 17 23:03:00 23:39:00
方法二:
更一般地说,通过检查哪些行与您的日期模式匹配,反之亦然,然后用bfill
or交换这些值ffill
:
match_pattern = df.apply(lambda x: x.str.match('\d{2}:\d{2}:\d{2}'))
numeric = df.where(~match_pattern).bfill(axis=1).dropna(how='any', axis=1)
dates = df.where(match_pattern).ffill(axis=1).dropna(how='any', axis=1)
df = pd.concat([numeric, dates], axis=1)
a b c d
0 0 10 22:58:00 23:27:00
1 10 17 23:03:00 23:39:00
2 0 0 23:27:00 23:27:00
3 10 10 23:39:00 23:39:00