Python:将字符串与整个下一列进行比较

Python:将字符串与整个下一列进行比较,python,pandas,string-comparison,Python,Pandas,String Comparison,我有以下数据帧: df1: 2000 2001 2002 a a a b b c c c d 因此,在2002年,值b被c取代。我现在想要的是检查每一列的每一个值,即a、b和c的值是否是下一列的成员。然后,我希望有一个a、b、c和d的输出,指示字符串成为第一个成员的日期以及它停止成为成员的日期。像这样: df2: a b c d

我有以下数据帧:

df1:
       2000 2001 2002 
        a    a     a 
        b    b     c
        c    c     d
因此,在2002年,值b被c取代。我现在想要的是检查每一列的每一个值,即a、b和c的值是否是下一列的成员。然后,我希望有一个a、b、c和d的输出,指示字符串成为第一个成员的日期以及它停止成为成员的日期。像这样:

df2: 
      a       b       c     d
      2000   2000   2000   2002
      NaN    2002   Nan    NaN
有谁能帮我用python实现这一点吗

编辑:这是我将如何开始,但我不知道如何在python中实现它

 for c in columns: 
     for v in column:
         drop v if v is not in c_[+1] 
 remove all empty columns        
理论上,这应该给我一个数据框,只显示带有删除值的日期。例如:

  df2: 
  2002 
   b

然后我会做一个类似的分析,但是对于添加的值,然后合并两个数据帧。但是,我不知道如何准确地将每一列转换为一个列表,并检查v是否是该列表的一部分,然后转到下一列。

将每一列解析为一个列表,然后从那里开始

input = ''' 2000 2001 2002 
        a    a     a 
        b    b     c
        c    c     d '''

lines = []
for line in input.split('\n'):
    print ' '.join(line.split())
    lines.append(line.split())

print lines
输出:

[['2000', '2001', '2002'], ['a', 'a', 'a'], ['b', 'b', 'c'], ['c', 'c', 'd']]

将每个列解析为一个列表,然后从那里开始

input = ''' 2000 2001 2002 
        a    a     a 
        b    b     c
        c    c     d '''

lines = []
for line in input.split('\n'):
    print ' '.join(line.split())
    lines.append(line.split())

print lines
输出:

[['2000', '2001', '2002'], ['a', 'a', 'a'], ['b', 'b', 'c'], ['c', 'c', 'd']]

这里要查看的一个有用工具是
pd.DataFrame().stack()

因为列名排序很好,所以可以对其排序,然后使用
drop\u duplicates()
获取:

df1.stack().sort_index(level=1).drop_duplicates()
Out[26]: 
0  2000    a
1  2000    b
2  2000    c
   2002    d
dtype: object

要将这些值转换为按值索引的年份,而不是按年索引的年份,您可以添加
.reset_index()。将_index(0)['level_1']
设置为以下任一值:

start = df1.stack().sort_index(level=1).drop_duplicates().reset_index().set_index(0)['level_1']
start
Out[31]: 
0
a    2000
b    2000
c    2000
d    2002
Name: level_1, dtype: object
在对另一个执行此操作后,将其称为
end
,您可以在由列构造的字典上使用
pd.Series().map()
,以获取第一个未显示值的字典的名称,而不是最后一个显示值的字典的名称

cols = df1.columns.tolist()+[np.nan]
next_col = {cols[i]:cols[i+1] for i in range(len(cols)-1)}
end = end.map(next_col)
end
Out[36]: 
0
b    2002
a     NaN
c     NaN
d     NaN
Name: level_1, dtype: object
然后,要将它们组合起来创建
df2
,可以使用
pd.concat

df2 = pd.concat([start, end], axis=1).T.reset_index(drop=True)

df2
Out[40]: 
      a     b     c     d
0  2000  2000  2000  2002
1   NaN  2002   NaN   NaN

这里要查看的一个有用工具是
pd.DataFrame().stack()

因为列名排序很好,所以可以对其排序,然后使用
drop\u duplicates()
获取:

df1.stack().sort_index(level=1).drop_duplicates()
Out[26]: 
0  2000    a
1  2000    b
2  2000    c
   2002    d
dtype: object

要将这些值转换为按值索引的年份,而不是按年索引的年份,您可以添加
.reset_index()。将_index(0)['level_1']
设置为以下任一值:

start = df1.stack().sort_index(level=1).drop_duplicates().reset_index().set_index(0)['level_1']
start
Out[31]: 
0
a    2000
b    2000
c    2000
d    2002
Name: level_1, dtype: object
在对另一个执行此操作后,将其称为
end
,您可以在由列构造的字典上使用
pd.Series().map()
,以获取第一个未显示值的字典的名称,而不是最后一个显示值的字典的名称

cols = df1.columns.tolist()+[np.nan]
next_col = {cols[i]:cols[i+1] for i in range(len(cols)-1)}
end = end.map(next_col)
end
Out[36]: 
0
b    2002
a     NaN
c     NaN
d     NaN
Name: level_1, dtype: object
然后,要将它们组合起来创建
df2
,可以使用
pd.concat

df2 = pd.concat([start, end], axis=1).T.reset_index(drop=True)

df2
Out[40]: 
      a     b     c     d
0  2000  2000  2000  2002
1   NaN  2002   NaN   NaN
通用算法:

1) 按年度将数据分组到列表中<代码>lzts=[[2000]、[a]、[b]、[c']、[2001]、[a]、[b]、[c']等]

2) 创建函数来循环列表,搜索给定值的实例

def search(val):
  ans = (float('NaN'), float('NaN')) #start & end date for given value
  for lzt in lzts:
    if val in lzt[1:]: #skip first value since its the year
      if math.isnan(ans[0]): #no start date yet
        ans[0] = lzt[0] #add the year
    else: #value not found
      if not math.isnan(ans[0]): #already has start date 
        ans[1] = lzt[0] #add the year as end date
注意:此解决方案假设一个值在一年内停止出现,它将永远消失。如果某个值在一年内未出现,然后返回,则结果将不准确。

通用算法:

1) 按年度将数据分组到列表中<代码>lzts=[[2000]、[a]、[b]、[c']、[2001]、[a]、[b]、[c']等]

2) 创建函数来循环列表,搜索给定值的实例

def search(val):
  ans = (float('NaN'), float('NaN')) #start & end date for given value
  for lzt in lzts:
    if val in lzt[1:]: #skip first value since its the year
      if math.isnan(ans[0]): #no start date yet
        ans[0] = lzt[0] #add the year
    else: #value not found
      if not math.isnan(ans[0]): #already has start date 
        ans[1] = lzt[0] #add the year as end date

注意:此解决方案假设一个值在一年内停止出现,它将永远消失。如果一个值在一年内没有出现,然后返回,则结果将不准确。

您是否尝试过解决方案?这是家庭作业吗?不确定我是否应该为你写一个算法不,这不是家庭作业。我在上面添加了一个尝试。你有没有尝试解决问题的方法?这是做作业用的吗?不确定我是否应该为你写一个算法不,这不是家庭作业。我添加了一个尝试。这非常有效,但仅适用于起始值,即df2中的索引为0。结束值始终是下一列。例如,我得到以下结果a:20002001 b:20002001,c:20002001。。。。我只是对end和start执行相同的程序,对吗?因为在运行完
start=df1.stack().sort_index(level=1).drop_duplicates().reset_index().set_index(0)['level_1']
I do
end=start
并执行其余部分后。错误可能是在
next_col={cols[I]:cols[I+1]中,对于范围内的I(len(cols)-1)}
cols[I+1]只指下一个单元格。我可能需要一个[last column]命令,对吗?
end
几乎与
start
相同,只是排序后保留最后一个副本,而不是第一个副本。这就是
.drop\u duplicates(keep='last')
中的
keep='last'
参数的作用。通过将
end
ascending=False
传递到
.sort_index()
,您可以得到类似的结果,不过我认为最好提供存储已排序的堆叠数据帧的选项作为中间步骤
nextcol
应该只引用下一个单元格–否则,即使使用
keep='last'
end
也会拉取显示值的最后一列,而不是不再显示值的第一列。哇。这非常有效,但仅适用于起始值,即df2中的索引为0。结束值始终是下一列。例如,我得到以下结果a:20002001 b:20002001,c:20002001。。。。我只是对end和start执行相同的程序,对吗?因为在运行完
start=df1.stack().sort_index(level=1).drop_duplicates().reset_index().set_index(0)['level_1']
I do
end=start
并执行其余部分后。错误可能是在
next_col={cols[I]:cols[I+1]中,对于范围内的I(len(cols)-1)}
cols[I+1]只指下一个单元格。我可能需要一个[last column]命令,对吗?
end
几乎与
start
相同,只是排序后保留最后一个副本,而不是第一个副本。这就是
中的
keep='last'
参数所做的。在
结束中删除重复项(keep='last')