无for循环处理数据帧

2024-06-26 18:28:55 发布

您现在位置:Python中文网/ 问答频道 /正文

下面列出了一个非常非结构化的数据框架。目标是将信息组合成5行数据帧(将字符串组合在第0-3、4-8、9-10、11-15和16行的项目中;代码在同一行集中是相同的;代码不是唯一的)。我能够得到起始索引的索引(0,4,9,11,16…;起始行的前一行有一列'code',值为'nan'),而不使用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

Tags: 数据字符串代码框架信息目标forcode
3条回答

你能检查一下这个代码是否适合你吗?(我编辑了代码)

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("''",""))

在使用唯一代码创建了有效的分组列之后,可以使用groupby执行此操作。你知道吗

如果每个组的所有行都是连续的,并且标识新组的逻辑是:

The previous row of a starting row has column 'code' with value 'nan'

当前一个代码值为null时,只需检查代码值是否为null。您可以通过将'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删除不需要的'字符,因为所有字符都被顶点包围。
您可以通过执行ddf.reset_index(drop=True, inplace=True)来摆脱'uniquecode'索引

如果你定义

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'] + "'"

相关问题 更多 >