【问题标题】:Pandas. Picking a column name based on row data熊猫。根据行数据选择列名
【发布时间】:2020-09-14 14:07:57
【问题描述】:

在我的previous question 中,我试图计算空白并构建一个包含新列的数据框以供后续分析。这个问题太详尽了,我决定将其拆分用于不同的目的。

我有我的初始数据集:

import pandas as pd
import numpy as np

df = pd.DataFrame({'id':[1000,2000,3000,4000],
               '201710':[7585,  4110,   4498,   np.nan],
               '201711':[7370,  3877,   4850,   4309],
               '201712':[6505,    np.nan,   4546,   4498],
               '201801':[7473,    np.nan,     np.nan,   4850],
               '201802':[6183,    np.nan,     np.nan,   np.nan ],
               '201803':[6699,  4558,   1429,   np.nan ],
               '201804':[ 118,  4152,   1429,   np.nan ],
               '201805':[  np.nan,  4271,   1960,   np.nan ],
               '201806':[  np.nan,    np.nan,   1798,   np.nan ],
               '201807':[  np.nan,    np.nan,   1612,   4361],
               '201808':[  np.nan,    np.nan,   1612,   4272],
               '201809':[  np.nan,  3900,   1681,   4199] ,
               
               })

我需要获取每个 id 的每个分数(非空白)的开始日期和结束日期。 我设法获得了第一次发生的开始数据和最后一次发生的结束数据,但不是在中间。然后,我计算了每个空白处的空白(以供进一步分析)

代码在这里(可能看起来很混乱):

# to obtain the  first and  last occurrence with data
res = pd.melt(df, id_vars=['id'], value_vars=df.columns[1:])
res.dropna(subset=['value'], inplace=True)
res.sort_values(by=['id', 'variable', 'value'], ascending=[True, True, True], 
inplace=True)

minimum_date = res.drop_duplicates(subset=['id'], keep='first')
maximum_date = res.drop_duplicates(subset=['id'], keep='last')

minimum_date.rename(columns={'variable': 'start_date'}, inplace=True)
maximum_date.rename(columns={'variable': 'end_date'}, inplace=True)


# To obtain number of gaps (nulls) and their length
res2 = pd.melt(df, id_vars=['id'], value_vars=df.columns[1:])
res2.sort_values(by=['id', 'variable'], ascending=[True, True], inplace=True)
res2=res2.replace(np.nan, 0)
m = res2.value.diff().ne(0).cumsum().rename('gid')    
gaps = res2.groupby(['id', 
m]).value.value_counts().loc[:,:,0].droplevel(-1).reset_index()


# add columns to main dataset with start- and end dates and gaps
df = pd.merge(df, minimum_date[['id', 'start_date']], on=['id'], how='left')
df = pd.merge(df, maximum_date[['id', 'end_date']], on=['id'], how='left')

我来到这样的数据集,其中 start_date 是第一个 notnull 出现,end_date - 最后一个 notnull 出现和 1-,2-,3- 空白是带有空白计数以供进一步分析的分数:

输出旨在有额外的列:

【问题讨论】:

  • 能否请您在问题中以文本形式发布您的示例,因为不鼓励使用 SO 上的图像。
  • @RavinderSingh13,我试图这样做,但它的数据太多..变得困惑。如果您在问题中运行脚本,您将获得输入,并且输出具有附加列,这些列是每个片段的开始和结束日期以及数据(不是空白)
  • 请发布您尝试运行的代码并更好地解释您要做什么
  • @gtomer,我已经编辑了这个问题。我到了这一步,我不知道如何进一步解决

标签: python pandas


【解决方案1】:

这是一个可能有用的函数,IIUC。

import pandas as pd

# create test data
t = pd.DataFrame({'x': [10, 20] + [None] * 3 + [30, 40, 50, 60] + [None] * 5 + [70]})

创建一个函数来查找每个“组”的开始位置、结束位置和大小,其中组是重复值的序列(例如,NaN):

def extract_nans(df, field):
    df = df.copy()
    
    # identify NaNs
    df['is_na'] = df[field].isna()

    # identify groups (sequence of identical values is a group):  X Y X => 3 groups
    df['group_id'] = (df['is_na'] ^ df['is_na'].shift(1)).cumsum()

    # how many members in this group?
    df['group_size'] = df.groupby('group_id')['group_id'].transform('size')

    # initial, final index of each group
    df['min_index'] = df.reset_index().groupby('group_id')['index'].transform(min)
    df['max_index'] = df.reset_index().groupby('group_id')['index'].transform(max)

    return df

结果:

summary = extract_nans(t, 'x')
print(summary)

       x  is_na  group_id  group_size  min_index  max_index
0   10.0  False         0           2          0          1
1   20.0  False         0           2          0          1
2    NaN   True         1           3          2          4
3    NaN   True         1           3          2          4
4    NaN   True         1           3          2          4
5   30.0  False         2           4          5          8
6   40.0  False         2           4          5          8
7   50.0  False         2           4          5          8
8   60.0  False         2           4          5          8
9    NaN   True         3           5          9         13
10   NaN   True         3           5          9         13
11   NaN   True         3           5          9         13
12   NaN   True         3           5          9         13
13   NaN   True         3           5          9         13
14  70.0  False         4           1         14         14

现在,您可以从摘要中排除“x”、删除重复项、过滤以仅保留 NaN 值(is_na == True)、过滤以使序列保持在一定长度以上(例如,至少 3 个连续的 NaN 值),等等。然后,如果你删除重复项,第一行将总结第一次 NaN 运行,第二行将总结第二次 NaN 运行,等等。

最后,如果你需要的话,你可以用它和 apply() 来处理整个数据框。

短版结果,用于测试数据框:

print(summary[summary['is_na']].drop(columns='x').drop_duplicates())
   is_na  group_id  group_size  min_index  max_index
2   True         1           3          2          4
9   True         3           5          9         13

【讨论】:

  • 非常感谢。这看起来像我需要的。我将仔细查看代码以更好地理解它。伙计们,我喜欢和你们一起学习有关 python 的新知识!!!
  • @jsmart,非常感谢!你的例子很有帮助!
猜你喜欢
  • 1970-01-01
  • 2015-08-15
  • 1970-01-01
  • 1970-01-01
  • 2018-08-05
  • 2015-10-23
相关资源
最近更新 更多