假设一个像这样的数据框:
df = pd.DataFrame([[1,2,3,4],[5,6,7,8],[9,10,11,12]], columns = ['A', 'B', 'A1', 'B1'])
我想要一个看起来像这样的数据框:
什么行不通:
new_rows = int(df.shape[1]/2) * df.shape[0]
new_cols = 2
df.values.reshape(new_rows, new_cols, order='F')
当然我可以遍历数据并创建一个新的列表列表,但必须有更好的方法。有什么想法吗?
答案 0 :(得分:8)
您可以使用lreshape
,用于列id
numpy.repeat
:
a = [col for col in df.columns if 'A' in col]
b = [col for col in df.columns if 'B' in col]
df1 = pd.lreshape(df, {'A' : a, 'B' : b})
df1['id'] = np.repeat(np.arange(len(df.columns) // 2), len (df.index)) + 1
print (df1)
A B id
0 1 2 1
1 5 6 1
2 9 10 1
3 3 4 2
4 7 8 2
5 11 12 2
编辑:
lreshape
目前尚未记录,但可能会将其删除(with pd.wide_to_long too)。
可能的解决方案是将所有3个函数合并为一个 - 也许melt
,但现在它没有实现。也许在一些新版本的熊猫中。然后我的答案会更新。
答案 1 :(得分:5)
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL
, registro DATETIME NOT NULL
,status ENUM('in','out') NOT NULL
,PRIMARY KEY(id,registro)
);
INSERT INTO my_table VALUES
(1,'2017-08-23 08:00:00','in'),
(1,'2017-08-23 12:00:00','out'),
(2,'2017-08-23 12:40:00','in'),
(1,'2017-08-23 13:00:00','in'),
(1,'2017-08-23 17:00:00','out');
SELECT id
, DATE(user_in) date
, SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(user_out,user_in)))) total
FROM
( SELECT x.id,x.registro user_in,MIN(y.registro) user_out
FROM my_table x
JOIN my_table y
ON y.id = x.id
AND y.registro > x.registro
AND y.status = 'out'
WHERE x.status = 'in'
GROUP
BY x.id, x.registro
) a
GROUP
BY id,date;
+----+------------+----------+
| id | date | total |
+----+------------+----------+
| 1 | 2017-08-23 | 08:00:00 |
+----+------------+----------+
函数几乎完全针对这种情况构建,其中有许多相同的变量前缀以不同的数字后缀结尾。这里唯一的区别是你的第一组变量没有后缀,所以你需要先重命名你的列。
pd.wide_to_long
唯一的问题是它必须有一个标识变量pd.wide_to_long
,与i
不同。 melt
用于创建此唯一标识列,稍后将删除该列。我想这可能会在将来得到纠正。
reset_index
答案 2 :(得分:2)
我分3步解决了这个问题:
df2
,仅保留您要添加到初始数据框df
的数据。df
数据(以及用于制作df2
的数据。df2
附加到df
。像这样:
# step 1: create new dataframe
df2 = df[['A1', 'B1']]
df2.columns = ['A', 'B']
# step 2: delete that data from original
df = df.drop(["A1", "B1"], 1)
# step 3: append
df = df.append(df2, ignore_index=True)
请注意当您执行df.append()
时需要指定ignore_index=True
,以便新列附加到索引而不是保留旧索引。
您的最终结果应该是您的原始数据框,并按照您的要求重新排列数据:
In [16]: df
Out[16]:
A B
0 1 2
1 5 6
2 9 10
3 3 4
4 7 8
5 11 12
答案 3 :(得分:1)
像这样使用pd.concat()
:
#Split into separate tables
df_1 = df[['A', 'B']]
df_2 = df[['A1', 'B1']]
df_2.columns = ['A', 'B'] # Make column names line up
# Add the ID column
df_1 = df_1.assign(id=1)
df_2 = df_2.assign(id=2)
# Concatenate
pd.concat([df_1, df_2])