重塑大熊猫数据框

时间:2017-03-21 13:43:21

标签: python pandas dataframe reshape lreshape

假设一个像这样的数据框:

df = pd.DataFrame([[1,2,3,4],[5,6,7,8],[9,10,11,12]], columns = ['A', 'B', 'A1', 'B1'])

enter image description here

我想要一个看起来像这样的数据框:

enter image description here

什么行不通:

new_rows = int(df.shape[1]/2) * df.shape[0]
new_cols = 2
df.values.reshape(new_rows, new_cols, order='F')

当然我可以遍历数据并创建一个新的列表列表,但必须有更好的方法。有什么想法吗?

4 个答案:

答案 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步解决了这个问题:

  1. 创建一个新的数据框df2,仅保留您要添加到初始数据框df的数据。
  2. 删除将在下面添加的df数据(以及用于制作df2的数据。
  3. df2附加到df
  4. 像这样:

    # 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])