我下面列出了一个非常非结构化的数据框。目标是将信息组合成5行数据框(将字符串合并到第0-3、4-8、9-10、11-15和16行的项目中;代码在同一行集中是相同的;代码不是唯一的)。我能够获得起始索引的索引(0,4,9,11,16 ...; 起始行的上一行具有值'nan'的列'code')不使用for循环。但是我想不办法不使用for循环来组合这些行。有人可以帮忙吗?谢谢!
code item01 item02 item03 item04 item05
0 1111 'a' 123 234 345 440
1 1111 'b' nan nan nan nan
2 nan 'c' nan nan nan nan
3 nan 'd' nan nan nan nan
4 2222 'b' 123 234 345 456
5 2222 'b' nan nan nan nan
6 nan 'c' nan nan nan nan
7 nan 'd' nan nan nan nan
8 nan 'e' nan nan nan nan
9 3333 'd' 123 234 345 456
10 nan 'b' nan nan nan nan
11 1111 'c' 123 234 345 456
12 1111 'b' nan nan nan nan
13 nan 'c' nan nan nan nan
14 nan 'd' nan nan nan nan
15 nan 'e' nan nan nan nan
16 5555 'a' nan nan nan nan
预期结果:
code item01 item02 item03 item04 item05
0 1111 'abcd' 123 234 345 440
1 2222 'bbcde' 123 234 345 456
2 3333 'db' 123 234 345 456
3 1111 'cbcde' 123 234 345 456
4 5555 'a' 123 234 345 456
答案 0 :(得分:4)
如果您定义
code_notnull = pd.notnull(df['code'])
然后您可以使用来标识每个新组的开始
# True when the row is not null, but the prior row is null
mask = code_notnull & ~(code_notnull.shift(1, fill_value=False))
0 True
1 False
2 False
3 False
4 True
...
然后您可以使用来定义组号
group_num = mask.cumsum()
0 1
1 1
2 1
3 1
4 2
...
,然后按group_num
分组:
import numpy as np
import pandas as pd
nan = np.nan
df = pd.DataFrame({'code': [1111.0, 1111.0, nan, nan, 2222.0, 2222.0, nan, nan, nan, 3333.0, nan,
1111.0, 1111.0, nan, nan, nan, 5555.0], 'item01': ['a', 'b', 'c', 'd',
'b', 'b', 'c', 'd', 'e', 'd', 'b', 'c', 'b', 'c', 'd',
'e', 'a'], 'item02': [123.0, nan, nan, nan, 123.0, nan, nan, nan, nan,
123.0, nan, 123.0, nan, nan, nan, nan, nan], 'item03': [234.0, nan, nan, nan,
234.0, nan, nan, nan, nan, 234.0, nan, 234.0, nan, nan, nan, nan, nan],
'item04': [345.0, nan, nan, nan, 345.0, nan, nan, nan, nan, 345.0, nan, 345.0,
nan, nan, nan, nan, nan], 'item05': [440.0, nan, nan, nan, 456.0, nan, nan,
nan, nan, 456.0, nan, 456.0, nan, nan, nan, nan, nan]})
code_notnull = pd.notnull(df['code'])
mask = code_notnull & ~(code_notnull.shift(1, fill_value=False))
group_num = mask.cumsum()
# Forward-fill all NaNs.
df = df.ffill()
grouped = df.groupby(group_num)
result = grouped.first()
result['item01'] = grouped['item01'].sum()
print(result)
收益
code item01 item02 item03 item04 item05
code
1 1111.0 abcd 123.0 234.0 345.0 440.0
2 2222.0 bbcde 123.0 234.0 345.0 456.0
3 3333.0 db 123.0 234.0 345.0 456.0
4 1111.0 cbcde 123.0 234.0 345.0 456.0
5 5555.0 a 123.0 234.0 345.0 456.0
请注意,以上我假设您在item01
中的字符串不以单引号开头和结尾。
如果这样做,您可以使用
df['item01'] = df['item01'].str[1:-1]
然后按照上述步骤进行。
import numpy as np
import pandas as pd
nan = np.nan
df = pd.DataFrame({'code': [1111.0, 1111.0, nan, nan, 2222.0, 2222.0, nan, nan, nan, 3333.0, nan,
1111.0, 1111.0, nan, nan, nan, 5555.0], 'item01': ["'a'", "'b'", "'c'", "'d'",
"'b'", "'b'", "'c'", "'d'", "'e'", "'d'", "'b'", "'c'", "'b'", "'c'", "'d'",
"'e'", "'a'"], 'item02': [123.0, nan, nan, nan, 123.0, nan, nan, nan, nan,
123.0, nan, 123.0, nan, nan, nan, nan, nan], 'item03': [234.0, nan, nan, nan,
234.0, nan, nan, nan, nan, 234.0, nan, 234.0, nan, nan, nan, nan, nan],
'item04': [345.0, nan, nan, nan, 345.0, nan, nan, nan, nan, 345.0, nan, 345.0,
nan, nan, nan, nan, nan], 'item05': [440.0, nan, nan, nan, 456.0, nan, nan,
nan, nan, 456.0, nan, 456.0, nan, nan, nan, nan, nan]})
df['item01'] = df['item01'].str[1:-1]
print(df)
收益(df['item0']
中的单引号已删除)
code item01 item02 item03 item04 item05
0 1111.0 a 123.0 234.0 345.0 440.0
1 1111.0 b NaN NaN NaN NaN
2 NaN c NaN NaN NaN NaN
3 NaN d NaN NaN NaN NaN
...
如果要将单引号添加回最终结果,可以使用:
result['item01'] = "'" + result['item01'] + "'"
答案 1 :(得分:1)
在创建具有唯一代码的有效分组列之后,可以使用groupby
进行操作。
如果每个组的所有行都是连续的,并且标识新组的逻辑是:
起始行的上一行包含列
'code'
,其值为'nan'
您只需要检查上一个为空时的代码值不为空。您可以通过将'code'
列移动一并通过列表理解来检查已移位列和原始列的值。
然后,累积总和将为分组创建唯一的值。
df['uniquecode'] = [pd.notnull(curr) and pd.isnull(prev) for curr, prev in zip(df['code'], df['code'].shift(1))]
df['uniquecode'] = df['uniquecode'].cumsum()
ddf = df.groupby('uniquecode').agg({'code':'mean', 'item01':'sum', 'item02':'sum', 'item03':'sum', 'item04':'sum', 'item05':'sum'}))
ddf['item01'] = ddf['item01'].apply(lambda x : "'" + x.replace("'","") + "'")
这将返回ddf
:
code item01 item02 item03 item04 item05
uniquecode
1 1111.0 'abcd' 123.0 234.0 345.0 440.0
2 2222.0 'bbcde' 123.0 234.0 345.0 456.0
3 3333.0 'db' 123.0 234.0 345.0 456.0
4 1111.0 'cbcde' 123.0 234.0 345.0 456.0
5 5555.0 'a' 0.0 0.0 0.0 0.0
最后一行使用apply
删除了不需要的'
字符,因为您的所有字符都被顶点包围。
您可以通过执行'uniquecode'
ddf.reset_index(drop=True, inplace=True)
索引
答案 2 :(得分:0)
您可以检查此代码是否适合您? (我编辑了代码)
df1=df.ffill()
df1['prev_code']=df1['code'].shift(1)
df1['grkey']=df1.reset_index().apply(lambda x: x['index'] if x.code!=x.prev_code else float('nan'), axis=1)
df1=df1.ffill().groupby('grkey').agg({'code':'first', 'item01':'sum','item02':'first','item03':'first','item04':'first','item05':'first'}).reset_index().drop('grkey',axis=1)
df1['item01']=df1['item01'].apply(lambda x: x.replace("''",""))